QML PinchArea 无法按预期与 QML Flickable 一起工作
QML PinchArea not working as expected with QML Flickable
所以我正在实现一个简单的图像查看器,并希望在 Flickable
中实现双指缩放。看了几个例子后,我遇到了 this 并认为我可以做类似的事情。但是,当我测试代码时(Android 上的 Qt 5.13)它没有按预期工作。问题是当图像被缩放时,PinchArea
停止工作并且用户无法缩小,而 Flickable
仍然允许 "flick" 图像(在该缩放级别)。这是代码,我找不到任何错误:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Flickable Image Zoom Example")
Page {
id: imagePage
property string imgUrl: "qrc:/messi.jpg"
property string strHpTitle: ""
property string strThumbnailUrl: ""
anchors.fill: parent
Flickable {
id: imageFlickable
anchors.fill: parent
contentWidth: imageContainer.width; contentHeight: imageContainer.height
clip: true
onHeightChanged: if (imagePreview.status === Image.Ready) imagePreview.fitToScreen();
Item {
id: imageContainer
width: Math.max(imagePreview.width * imagePreview.scale, imageFlickable.width)
height: Math.max(imagePreview.height * imagePreview.scale, imageFlickable.height)
Image {
id: imagePreview
property real prevScale
function fitToScreen() {
scale = Math.min(imageFlickable.width / width, imageFlickable.height / height, 1)
pinchArea.minScale = scale
prevScale = scale
}
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
cache: false
asynchronous: true
source: imagePage.imgUrl
sourceSize.height: 1000;
smooth: !imageFlickable.moving
onStatusChanged: {
if (status == Image.Ready) {
fitToScreen()
}
}
onScaleChanged: {
if ((width * scale) > imageFlickable.width) {
var xoff = (imageFlickable.width / 2 + imageFlickable.contentX) * scale / prevScale;
imageFlickable.contentX = xoff - imageFlickable.width / 2
}
if ((height * scale) > imageFlickable.height) {
var yoff = (imageFlickable.height / 2 + imageFlickable.contentY) * scale / prevScale;
imageFlickable.contentY = yoff - imageFlickable.height / 2
}
prevScale = scale
}
}
}
PinchArea {
id: pinchArea
property real minScale: 1.0
property real maxScale: 3.0
anchors.fill: parent
pinch.target: imagePreview
pinch.minimumScale: minScale
pinch.maximumScale: maxScale
pinch.dragAxis: Pinch.XandYAxis
onPinchFinished: {
imageFlickable.returnToBounds()
}
}
}
}
}
好的,所以我找到了解决这个问题的方法。这个问题(我认为)是由于一个错误。由于某些奇怪的原因,我代码中的 Flickable
从 PinchArea
窃取了触摸事件,因此捏合触摸事件被忽略并传递给 Flickable
。为了解决这个问题,我找到了一个解决方法,它包括在 PinchArea
中创建一个 MouseArea
,这允许 PinchArea
接收触摸事件,以便 Flickable
不偷他们。因此,通过解决方法,我的代码具有以下结构:
Flickable{
PinchArea{
MouseArea{ anchors.fill: parent} // this is the workaround
}
Item{}
}
我已经报告了错误 here 并上传了一个显示原因的小视频。
所以我正在实现一个简单的图像查看器,并希望在 Flickable
中实现双指缩放。看了几个例子后,我遇到了 this 并认为我可以做类似的事情。但是,当我测试代码时(Android 上的 Qt 5.13)它没有按预期工作。问题是当图像被缩放时,PinchArea
停止工作并且用户无法缩小,而 Flickable
仍然允许 "flick" 图像(在该缩放级别)。这是代码,我找不到任何错误:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Flickable Image Zoom Example")
Page {
id: imagePage
property string imgUrl: "qrc:/messi.jpg"
property string strHpTitle: ""
property string strThumbnailUrl: ""
anchors.fill: parent
Flickable {
id: imageFlickable
anchors.fill: parent
contentWidth: imageContainer.width; contentHeight: imageContainer.height
clip: true
onHeightChanged: if (imagePreview.status === Image.Ready) imagePreview.fitToScreen();
Item {
id: imageContainer
width: Math.max(imagePreview.width * imagePreview.scale, imageFlickable.width)
height: Math.max(imagePreview.height * imagePreview.scale, imageFlickable.height)
Image {
id: imagePreview
property real prevScale
function fitToScreen() {
scale = Math.min(imageFlickable.width / width, imageFlickable.height / height, 1)
pinchArea.minScale = scale
prevScale = scale
}
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
cache: false
asynchronous: true
source: imagePage.imgUrl
sourceSize.height: 1000;
smooth: !imageFlickable.moving
onStatusChanged: {
if (status == Image.Ready) {
fitToScreen()
}
}
onScaleChanged: {
if ((width * scale) > imageFlickable.width) {
var xoff = (imageFlickable.width / 2 + imageFlickable.contentX) * scale / prevScale;
imageFlickable.contentX = xoff - imageFlickable.width / 2
}
if ((height * scale) > imageFlickable.height) {
var yoff = (imageFlickable.height / 2 + imageFlickable.contentY) * scale / prevScale;
imageFlickable.contentY = yoff - imageFlickable.height / 2
}
prevScale = scale
}
}
}
PinchArea {
id: pinchArea
property real minScale: 1.0
property real maxScale: 3.0
anchors.fill: parent
pinch.target: imagePreview
pinch.minimumScale: minScale
pinch.maximumScale: maxScale
pinch.dragAxis: Pinch.XandYAxis
onPinchFinished: {
imageFlickable.returnToBounds()
}
}
}
}
}
好的,所以我找到了解决这个问题的方法。这个问题(我认为)是由于一个错误。由于某些奇怪的原因,我代码中的 Flickable
从 PinchArea
窃取了触摸事件,因此捏合触摸事件被忽略并传递给 Flickable
。为了解决这个问题,我找到了一个解决方法,它包括在 PinchArea
中创建一个 MouseArea
,这允许 PinchArea
接收触摸事件,以便 Flickable
不偷他们。因此,通过解决方法,我的代码具有以下结构:
Flickable{
PinchArea{
MouseArea{ anchors.fill: parent} // this is the workaround
}
Item{}
}
我已经报告了错误 here 并上传了一个显示原因的小视频。