概述
这篇文章将要介绍Qml中如何实现拖拽功能。实现拖拽并释放控件需要下面几个步骤:
- 为控件添加鼠标响应事件,监听鼠标移动的横纵坐标。
- 根据鼠标的位置移动控件位置。
- 修改控件的宿主。
处理鼠标事件
为了处理鼠标事件,我们可以在qml文件中添加一个MouseArea对象。这个对象有位置和大小,但是不可见。这里为了演示MouseArea的使用,我们先添加一个click事件监听。
Rectangle{
width: 100
height: 100
color: "green"
MouseArea{
anchors.fill:parent
onClicked: {
console.debug("onClick MouseArea")
}
}
}
为了实现拖拽功能,我们需要监听更具体的一些事件。包括press事件、move事件、release事件。
MouseArea{
anchors.fill:parent
onClicked: {
console.debug("onClick MouseArea")
}
onPressed: {
console.debug("onPressed x:",mouseX," y:",mouseY)
}
onPositionChanged: {
console.debug("onPositionChanged x:",mouseX," y:",mouseY)
}
onReleased: {
console.debug("onReleased x:",mouseX," y:",mouseY)
}
}
onPressed监听鼠标按下事件,onPositionChanged监听鼠标位置变化,onRelease监听鼠标的释放事件。
移动控件
我们可以通过改变控件的x和y坐标来移动控件,这里先将mouseX和mouseY直接赋值给控件。
Rectangle{
id:rect
width: 100
height: 100
color: "green"
MouseArea{
anchors.fill:parent
onClicked: {
console.debug("onClick MouseArea")
}
onPressed: {
console.debug("onPressed x:",mouseX," y:",mouseY)
rect.x = mouseX
rect.y = mouseY
}
onPositionChanged: {
console.debug("onPositionChanged x:",mouseX," y:",mouseY)
rect.x = mouseX
rect.y = mouseY
}
onReleased: {
console.debug("onReleased x:",mouseX," y:",mouseY)
rect.x = mouseX
rect.y = mouseY
}
}
}
运行后进行拖拽实验,我们发现矩形框不断跳动,与我们期待的结构相差甚远。这里的MouseArea在矩形内部,在拖拽过程中不断修改矩形框的位置,矩形框的位置变换又影响mouseX和mouseY的值,所以矩形框跳动得厉害。如何解决这个问题呢?
- 不能直接使用mouseX和mouseY的值,因为这两个值依赖矩形位置。
- 通过x和y两个方向上的偏移量控制矩形移动。
使用Item的mapToGlobal 方法将mouseX和mouseY转换成globalX和globalY,避免修改矩形位置后影响MouseArea位置移动计算。通过记录前后两次的位置偏移量移动矩形。
Rectangle{
id:rect
width: 100
height: 100
x:300
y:300
color: "green"
MouseArea{
anchors.fill:parent
property real lastX: 0
property real lastY: 0
onClicked: {
console.debug("onClick MouseArea")
}
onPressed: {
var coordinate = mapToGlobal(mouseX,mouseY)
lastX = coordinate.x
lastY = coordinate.y
}
onPositionChanged: {
var coordinate = mapToGlobal(mouseX,mouseY)
var offsetX = coordinate.x - lastX
var offsetY = coordinate.y - lastY
lastX = coordinate.x
lastY = coordinate.y
rect.x += offsetX
rect.y += offsetY
}
onReleased: {
var coordinate = mapToGlobal(mouseX,mouseY)
var offsetX = coordinate.x - lastX
var offsetY = coordinate.y - lastY
lastX = coordinate.x
lastY = coordinate.y
rect.x += offsetX
rect.y += offsetY
}
}
}
经过上面的修改后,矩形拖拽的过程变得特别的顺畅了。
修改宿主
修改宿主指的是修改矩形框的parent,进而改变对象树结构和渲染树结构。
首先我们在拖拽释放的时候需要判断是否要修改矩形框的宿主,使用哪个宿主。这个处理过程需要根据鼠标释放时的坐标位置来判断。
function dockToHost(dragItem, globalX, globalY){
var local = host1.mapFromGlobal(globalX,globalY)
if(host1.contains(local)){
dragItem.x = 0
dragItem.y = 0
dragItem.z = 100
dragItem.parent = host1
return
}
local = host2.mapFromGlobal(globalX, globalY)
if(host2.contains(local)){
dragItem.x = 0
dragItem.y = 0
dragItem.z = 100
dragItem.parent = host2
return
}
}
Rectangle{
id:host1
width: 120
height: 120
x:100
y:100
color: "red"
}
Rectangle{
id:host2
width: 150
height: 150
x:220
y:220
color: "blue"
}
鼠标释放的时候调用dockToHost方法用于确定矩形框改变到哪个宿主上。这里还调用了Item的mapFromGlobal方法将全局坐标转换成item本地坐标,然后判断是否在item区域内。找到宿主item后将矩形框的parent修改成宿主item并将矩形框的坐标重置。
总结
经过上面的步骤后我们可以实现一个简单的控件拖拽功能,并且通过拖拽控件可以改判控件的宿主item。这里主要应用到了MouseArea控件监听鼠标事件,通过改变矩形框的x和y偏移量修改位置。同时为了矩形框移动不影响到MouseArea的mouseX和mouseY,我们使用了mapToGlobal和mapFromGlobal方法来实现全局坐标与局部坐标的相互转换。然后我们通过修改矩形框的parent来改变矩形框的宿主,为宿主item动态添加控件。
最后
以上就是简单猎豹为你收集整理的Qt中如何实现拖拽释放控件处理鼠标事件移动控件修改宿主总结的全部内容,希望文章能够帮你解决Qt中如何实现拖拽释放控件处理鼠标事件移动控件修改宿主总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复