在嵌套的鼠标区域中获取鼠标 x 和 y 并启用悬停



我制作了一个简化的MapImage组件,它允许使用鼠标缩放和平移图像。这个组件使用了Flickable和MouseArea组件。MapImage组件只处理图像显示、缩放和平移。我想在main中的MapImage实例中使用另一个MouseArea。qml(能够使用画布放置对象,但这在这里并不重要)。这不是MapImage的工作,所以我真的需要第二个MouseArea组件。

我需要设置hoverEnabled属性为true,因为我需要onPositionChanged和其他事件…但是这个属性似乎会导致从我的updateFlickable函数中获取的mouseX和mouseY值的问题。当我用鼠标滚轮缩放时,缩放不会发生在鼠标位置…

我在这里或要点中提供了一个最小的示例。

有解决这个问题的提示吗?

main.qml

import QtQml.Models 2.11
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
MapImage {
id: map
height: 600
width: 800
imageSource: "https://images.unsplash.com/photo-1651634099253-720df02a0d50"
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: true // this is required to use onPositionChanged
preventStealing: false
onPressed: {
// needed for flickable
mouse.accepted = false;
}
onPositionChanged: {
// do something.
}
}
}

MapImage.qml

import QtQuick 2.11
Item {
id: root
property alias imageSource: image.source
Flickable {
id: flickable
anchors.fill: parent
contentWidth: props.originalImageWidth
contentHeight: props.originalImageHeight
Image {
id: image
fillMode: Image.PreserveAspectFit
onStatusChanged: {
if (status === Image.Ready) {
props.originalImageWidth = sourceSize.width;
props.originalImageHeight = sourceSize.height;
props.changeCurrentScale(1);
}
}
// define the image display size
width: flickable.contentWidth;
height: flickable.contentHeight;
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: true
onWheel: {
wheel.accepted = false;
props.changeCurrentScale(wheel.angleDelta.y);
}
}
}
QtObject {
id: props
// original image size
property int originalImageWidth
property int originalImageHeight
property real scaleStep: 0.2
property real currentScale: 0.1
onCurrentScaleChanged: updateFlickable(currentScale);
function updateFlickable(scale) {
console.log(mouseArea.mouseX, mouseArea.mouseY); // <------ I am no longer able to get mouse x and y coordinates
flickable.resizeContent(originalImageWidth * scale, originalImageHeight * scale, Qt.point(mouseArea.mouseX, mouseArea.mouseY));
flickable.returnToBounds();
}
function changeCurrentScale(wheelDelta) {
if (wheelDelta > 0) currentScale = currentScale * (1 + scaleStep);
else currentScale = currentScale / (1 + scaleStep);
}
}
}
}

终于找到解决办法了。我必须在MapImage组件中添加一个新属性。此属性角色用于存储父坐标系统中父鼠标区域中鼠标的更新位置。在那之后,我必须使用mapToItem转换在flickable。内容项坐标系统。

main.qml

import QtQml.Models 2.11
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
MapImage {
id: map
height: 600
width: 800
imageSource: "https://images.unsplash.com/photo-1651634099253-720df02a0d50"
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: true // this is required to use onPositionChanged
preventStealing: false
onPressed: {
// needed for flickable
mouse.accepted = false;
}
onPositionChanged: {
// CHANGE HERE
// the position must be updated on every position change
map.parentMouseAreaPosition = Qt.point(mouse.x, mouse.y);
// TO HERE
}
}
}

MapImage.qml

import QtQuick 2.11
Item {
id: root
property alias imageSource: image.source
// CHANGE HERE
// the current mouse position in the parent mouse area in parent coordinate system
property var parentMouseAreaPosition: Qt.point(0, 0)
// this function maps the parent coordinate system to that of contentItem
function __mapToContentItem(x, y) {
return mapToItem(flickable.contentItem, x, y);
}
// TO HERE
Flickable {
id: flickable
anchors.fill: parent
contentWidth: props.originalImageWidth
contentHeight: props.originalImageHeight
Image {
id: image
fillMode: Image.PreserveAspectFit
onStatusChanged: {
if (status === Image.Ready) {
props.originalImageWidth = sourceSize.width;
props.originalImageHeight = sourceSize.height;
props.changeCurrentScale(1);
}
}
// define the image display size
width: flickable.contentWidth;
height: flickable.contentHeight;
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: true
onWheel: {
wheel.accepted = false;
props.changeCurrentScale(wheel.angleDelta.y);
}
}
}
QtObject {
id: props
// original image size
property int originalImageWidth
property int originalImageHeight
property real scaleStep: 0.2
property real currentScale: 0.1
onCurrentScaleChanged: updateFlickable(currentScale);
function updateFlickable(scale) {
// CHANGE HERE
// get the mapped point
let point = __mapToContentItem(root.parentMouseAreaPosition.x, root.parentMouseAreaPosition.y);
console.log(point.x, point.y);
flickable.resizeContent(originalImageWidth * scale, originalImageHeight * scale, point);
// TO HERE
flickable.returnToBounds();
}
function changeCurrentScale(wheelDelta) {
if (wheelDelta > 0) currentScale = currentScale * (1 + scaleStep);
else currentScale = currentScale / (1 + scaleStep);
}
}
}
}

我不知道是否有更好的解决办法。

最新更新