如何在qml图像组件中获得鼠标单击位置?



我试图在qml图像组件中获得鼠标单击位置,但我得到的不是真正的基于像素的图像位置,我如何才能获得图像的基于像素的位置?

这是我的QML代码
Image {
id: sourceImage
width: parent.width
height: parent.height
fillMode: Image.PreserveAspectFit
source: "D://test.png"
mipmap: true
smooth: true
antialiasing: true
MouseArea {
width: parent.width
height: parent.height
focus: true
anchors.fill: parent
onClicked: {
print("clicked:", mouse.x,mouse.y)
}
}
}

实际图像尺寸为3840*1260,但当我用鼠标点击右下角位置时,显示点击:683547

很多代码都是用于调试的样板。其中重要的部分是mapToImage()getXPosition()/getYPosition()这三个函数。后者用于在Image.PreservedAspectFit不能填充ImagehorizontalAlginment/verticalAlignment时获取图像绘制的偏移量。

map函数使用sourceSizepaintedWidth/paintedHeight来获得图像的原始大小与实际绘制的图像之间的比例。请记住,当更改sourceSize并且不让图像设置它时,这种获得缩放的方法可能无法工作。

文档中的注释:

sourceSize可以通过设置清除为图像的自然大小

import QtQuick
import QtQuick.Controls
Window {
id: root
visible: true
width: 800
height: 600
title: qsTr("Image Picking")
function getXPosition(image : Image) : real {
switch (image.horizontalAlignment) {
case Image.AlignLeft:
return 0
case Image.AlignRight:
return image.width - image.paintedWidth
case Image.AlignHCenter:
default:
return (image.width - image.paintedWidth) * 0.5
}
}
function getYPosition(image : Image) : real {
switch (image.verticalAlignment) {
case Image.AlignTop:
return 0
case Image.AlignBottom:
return image.height - image.paintedHeight
case Image.AlignVCenter:
default:
return (image.height - image.paintedHeight) * 0.5
}
}
function mapToImage(mouse : MouseEvent, image : Image) {
root.xScale = image.paintedWidth / image.sourceSize.width
root.yScale = image.paintedHeight / image.sourceSize.height
root.xImgPosition = Math.floor((mouse.x - root.getXPosition(image)) / root.xScale)
root.yImgPosition = Math.floor((mouse.y - root.getYPosition(image)) / root.yScale)
}
property real xScale: 0
property real yScale: 0
property real xImgPosition: 0
property real yImgPosition: 0
Image {
id: image
anchors.centerIn: parent
width: 320
height: 240
fillMode: Image.PreserveAspectFit
//horizontalAlignment: Image.AlignLeft
source: "https://picsum.photos/id/17/200/300"
mipmap: true
smooth: true
antialiasing: true
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onPositionChanged: function(mouse) { root.mapToImage(mouse, image) }
}
Rectangle {
anchors.fill: parent
color: "transparent"
border {
width: 1
color: "gray"
}
}
// Debug rectangle showing the real dimension of the image before clipping by the fillMode
Rectangle {
x: root.getXPosition(image)
y: root.getYPosition(image)
width: image.paintedWidth
height: image.paintedHeight
color: "transparent"
border {
width: 1
color: "red"
}
}
}
Rectangle {
width: column.width + 40
height: column.height + 40
color: Qt.rgba(0.3, 0.3, 0.3, 0.4)
Column {
id: column
x: 20
y: 20
spacing: 4
ComboBox {
width: 180
textRole: "text"
valueRole: "value"
onActivated: image.fillMode = currentValue
Component.onCompleted: currentIndex = indexOfValue(image.fillMode)
model: [
{ value: Image.Stretch, text: qsTr("Stretch") },
{ value: Image.PreserveAspectFit, text: qsTr("Preserve Aspect Fit") },
{ value: Image.PreserveAspectCrop, text: qsTr("Preserve Aspect Crop") }
]
}
Text { text: "Mouse:    " + mouseArea.mouseX + ", " + mouseArea.mouseY }
Text { text: "Image:    " + image.width + ", " + image.height }
Text { text: "Painted:  " + image.paintedWidth + ", " + image.paintedHeight }
Text { text: "Source:   " + image.sourceSize.width + ", " + image.sourceSize.height }
Text { text: "Scaling:  " + root.xScale + ", " + root.yScale }
Text { text: "Position: " + root.xImgPosition + ", " + root.yImgPosition }
}
}
}

最新更新