简介
本文是《Qml组件化编程》系列文章的第二篇,涛哥将教大家,如何在Qml中实现可拖动组件,通过拖动
改变组件的大小和位置;以及实现定制窗体(无边框和标题栏), 并把拖动组件应用在顶层窗体。
拖动组件
拖动改变坐标
拖动改变坐标的原理很简单,鼠标移动的时候改变目标Item的坐标即可。
说话的功夫,涛哥就造了个轮子出来
(其实是太常用了,涛哥已经写了很多遍)
import QtQuick 2.9
import QtQuick.Controls 2.5
Item {
width: 800
height: 600
Rectangle {
id: moveItem
//注意拖动目标不要使用锚布局或者Layout,而是使用相对坐标
x: 100
y: 100
width: 300
height: 200
color: "lightblue"
MouseArea {
anchors.fill: parent
property real lastX: 0
property real lastY: 0
onPressed: {
//鼠标按下时,记录鼠标初始位置
lastX = mouseX
lastY = mouseY
}
onPositionChanged: {
if (pressed) {
//鼠标按住的前提下,坐标改变时,计算偏移量,应用到目标item的坐标上即可
moveItem.x += mouseX - lastX
moveItem.y += mouseY - lastY
}
}
}
}
}
![9acffdfbb5048704f93ea2b19b684f67.gif](https://img-blog.csdnimg.cn/img_convert/9acffdfbb5048704f93ea2b19b684f67.gif)
上面例子中的MouseArea是拖动区域,Rectangle是要拖动的目标Item。
为了实现高度的可复用性,涛哥将MouseArea独立封装成一个组件,并提供一个control属性,
让外部使用组件实例的时候指定要拖动的目标。
// TMoveArea.qml
import QtQuick 2.9
MouseArea {
id: root
property real lastX: 0
property real lastY: 0
property bool mask: false //有时候外面需要屏蔽拖动,导出一个mask属性, 默认false。
property var control: parent //导出一个control属性,指定要拖动的目标, 默认就用parent好了。注意目标要有x和y属性并且可修改
onPressed: {
lastX = mouseX;
lastY = mouseY;
}
onContainsMouseChanged: { //修改一下鼠标样式,以示区别
if (containsMouse) {
cursorShape = Qt.SizeAllCursor;
} else {
cursorShape = Qt.ArrowCursor;
}
}
onPositionChanged: {
if (!mask && pressed && control)
{
control.x +=mouseX - lastX
control.y +=mouseY - lastY
}
}
}
TMoveArea组件的用法
Item {
anchors.fill: parent
Rectangle {
x: 100
y: 200
width: 400
height: 300
color: "darkred"
//实例化一个MoveArea
TMoveArea {
//指定control为parent。 其实默认就是parent,写出来示意一下
control: parent
anchors.fill: parent
}
}
}