前言
从本节开始,我们重新学习一下鼠标和键盘的应用。
其实在之前学习信号处理器的时候,就已经深入学习MouseArea鼠标相关的各种槽函数,并基于这些信号处理和一些临时变量,我们实现了矩形的拖拽。
以下是跳转链接:QML学习笔记(十五)QML的信号处理器(MouseArea)
代码量不多,这里顺便贴一下:
Window {
visible: true
width: 640
height: 480
title: qsTr("DragRect")
Rectangle {
id: rectId
width: 150; height: 150; color: "red"
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: true
property bool pressed: false
property real startSceneX: 0 // 按下时全局坐标
property real startSceneY: 0
property real startRectX: 0 // 按下时矩形左上角
property real startRectY: 0
onPressed: {
pressed = true
var scenePos = mapToItem(null, mouse.x, mouse.y) // 映射到窗口坐标
startSceneX = scenePos.x
startSceneY = scenePos.y
startRectX = rectId.x
startRectY = 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: dragContainerId
width:parent.width
height:200
color: "beige"
y: 250
Rectangle{
id: draggableRectId
width: 50
height: width
color: "blue"
}
MouseArea{
anchors.fill: parent
drag.target: draggableRectId
// drag.axis: Drag.XAxis
drag.axis: Drag.XAndYAxis
drag.minimumX: 0
drag.maximumX: dragContainerId.width - draggableRectId.width
}
}
运行效果:

可以看到,这段代码非常简洁,甚至没有重载任何的槽函数。
MouseArea{
anchors.fill: parent
drag.target: draggableRectId
// drag.axis: Drag.XAxis
drag.axis: Drag.XAndYAxis
drag.minimumX: 0
drag.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。但很多时候,我们希望点击了矩形再实现拖拽,甚至希望短暂长按矩形后,再进行拖拽。这种情形的话更适合用鼠标三态的信号处理来自行实现,一般我们只需要在自行简单计算坐标,也不是什么很难的方法。
QML的MouseArea的drag&spm=1001.2101.3001.5002&articleId=152413461&d=1&t=3&u=96ccb47f24434088a9744931655917ce)
255

被折叠的 条评论
为什么被折叠?



