QML学习笔记(二十三)QML的MouseArea的drag
前言
从本节开始,我们重新学习一下鼠标和键盘的应用。
其实在之前学习信号处理器的时候,就已经深入学习MouseArea鼠标相关的各种槽函数,并基于这些信号处理和一些临时变量,我们实现了矩形的拖拽。
以下是跳转链接:QML学习笔记(十五)QML的信号处理器(MouseArea)
代码量不多,这里顺便贴一下:
Window {visible: truewidth: 640height: 480title: qsTr("DragRect")Rectangle {id: rectIdwidth: 150; height: 150; color: "red"MouseArea {anchors.fill: parentacceptedButtons: Qt.LeftButtonhoverEnabled: trueproperty bool pressed: falseproperty real startSceneX: 0 // 按下时全局坐标property real startSceneY: 0property real startRectX: 0 // 按下时矩形左上角property real startRectY: 0onPressed: {pressed = truevar scenePos = mapToItem(null, mouse.x, mouse.y) // 映射到窗口坐标startSceneX = scenePos.xstartSceneY = scenePos.ystartRectX = rectId.xstartRectY = rectId.y}onPositionChanged: {if (pressed) {var curScene = mapToItem(null, mouse.x, mouse.y)rectId.x = startRectX + (curScene.x - startSceneX)rectId.y = startRectY + (curScene.y - startSceneY)}}onReleased: pressed = false}}
}
然而今天我们再重温一下MouseArea,并学习如何通过其drag方法来实现组件的拖拽,这将更加高效。
一、MouseAre和drag
先看以下帮助文档:
测试代码如下:
Rectangle{id: dragContainerIdwidth:parent.widthheight:200color: "beige"y: 250Rectangle{id: draggableRectIdwidth: 50height: widthcolor: "blue"}MouseArea{anchors.fill: parentdrag.target: draggableRectId
// drag.axis: Drag.XAxisdrag.axis: Drag.XAndYAxisdrag.minimumX: 0drag.maximumX: dragContainerId.width - draggableRectId.width}}
运行效果:
可以看到,这段代码非常简洁,甚至没有重载任何的槽函数。
MouseArea{anchors.fill: parentdrag.target: draggableRectId
// drag.axis: Drag.XAxisdrag.axis: Drag.XAndYAxisdrag.minimumX: 0drag.maximumX: dragContainerId.width - draggableRectId.width}
在这段代码中,我们给MouseArea的drag属性设置了对象target,此后这个target的移动代码便不需要我们手动处理了。我们仅仅需要设置最小最大的x和y范围即可()不出界。
它甚至还提供了axis这种属性,如果设置成drag.axis: Drag.XAxis ,则告诉 MouseArea 的拖拽功能,只能沿水平方向(X 轴)拖动,垂直方向被锁定,Y 坐标保持不变。
它的取值枚举:
Drag.XAxis → 水平拖拽
Drag.YAxis → 垂直拖拽
Drag.XAndYAxis → 双向自由拖拽(默认)
直观上看drag.axis: Drag.XAxis,就感觉y轴被锁了,怎么拖拽都只会让target在x轴上移动,这在某些情形下会有用。
二、对比两种方法
由于drag方法比较简单,且不需要自己计算,我就不多解释了。这里将之前的方法拿过来,和drag对比一下:
以下是kimi的总结:
两段代码都能“拖”,但底层思路完全不同:
-
手动坐标法(红矩形)
- 不用
drag.*
任何属性 - 完全靠
onPressed / onPositionChanged
自己算坐标 → 直接改x/y
- 自由度最高:可同时拖 X+Y、加惯性、旋转、缩放
- 代码量稍大,边界/轴约束都要自己写
- 不用
-
内置 drag 导轨法(蓝矩形)
- 一句
drag.target
告诉 MouseArea“替我拖” drag.axis / min / max
让 Qt 帮你做导轨+限位- 引擎层替你改
x
- 只能做平移;想同时拖 Y 就把
drag.axis
换成XAndYAxis
或再加drag.minimumY / maximumY
- 代码极简,适合“纯平移+硬边界”场景
- 一句
一句话总结:
“前者是‘自己拉车’,后者是‘Qt 给你铺轨道并推车’;要特效用手动,要快出平移用 drag。”
三、总结:
如果只是想实现简单拖拽的话,用drag方法是明智的选择。
但不要忘了,这种方法适用于在一个大的MouseArea范围中,拖拽一个指定的target。但很多时候,我们希望点击了矩形再实现拖拽,甚至希望短暂长按矩形后,再进行拖拽。这种情形的话更适合用鼠标三态的信号处理来自行实现,一般我们只需要在自行简单计算坐标,也不是什么很难的方法。