1) Rectangle에 Drag기능을 활성화한다.
2) DropArea에 이벤트별 상황을 설정한다.
3) DropArea에 마우스가 들어왔을때 확인을 위해 Rectangle을 포함시키고 색깔을 변경시킨다.
4) 이게 가장 중요한데 만약 Rectangle의 MouseArea에 onReleased: parent.Drag.drop()을 포함시키지 않는다면 드래그 & 드롭을 마치는 시점에 Drop이 아니라 Exit 이벤트가 발생한다. 그러므로 드롭이벤트를 발생시키려면 반드시 추가해야한다.
5) 또 다른 문제점은 DropArea와 Drag할 객체가 같은 스코프 안에 있어야 한다. 다른 스코프의 객체 내부의 DropArea에 접근하게 하려면 onDropped에 drop.accept()를 적어둬야 한다.
import QtQuick
import QtQuick.Controls
Window {
visible: true
width: 640
height: 480
DropArea {
anchors.fill: parent
onDropped: {
console.log("onDropped");
// drop.accept()
}
onEntered: {
console.log("onEntered");
}
onExited: {
console.log("onExited");
}
onPositionChanged: {
console.log(drag.x + ' ' + drag.y);
}
Rectangle {
anchors.fill: parent
color: parent.containsDrag ? "green" : "yellow"
}
}
Rectangle{
width: 100
height: 100
x: 0
y: 0
color: "blue"
MouseArea {
id: dragArea1
anchors.fill: parent
drag.target: parent
onReleased: parent.Drag.drop()
}
Drag.active: dragArea1.drag.active
Drag.hotSpot.x: dragArea1.width / 2
Drag.hotSpot.y: dragArea1.height / 2
}
}
좀 더 발전시켜보면
1) 만약 DropArea 안에 떨어뜨리면 Accept가 출력된다. 반면 밖에 떨어뜨리면 Reject가 출력되면서 원래의 위치로 돌아간다.
2) Drag와 Drop에 keys를 부여해서 해당 드래그와 드롭에만 반응하게 만들 수 있다
import QtQuick
import QtQuick.Controls
Window {
visible: true
width: 640
height: 480
DropArea {
id: droparea
anchors.fill: parent
keys: ["origin"]
onDropped: {
console.log("onDropped");
drop.accept()
}
onEntered: {
console.log("onEntered");
}
onExited: {
console.log("onExited");
}
onPositionChanged: {
console.log(drag.x + ' ' + drag.y);
}
}
Rectangle{
id: recta
width: 100
height: 100
x: 100
y: 200
color: "blue"
MouseArea {
id: dragArea1
anchors.fill: parent
drag.target: parent
acceptedButtons: Qt.AllButtons
property int ori_x
property int ori_y
onPressed: {
ori_x = recta.x;
ori_y = recta.y;
console.log(ori_x + ' ' + ori_y)
}
onReleased: {
if (parent.Drag.drop() !== Qt.IgnoreAction)
console.log("Accepted.");
else {
console.log("Rejected. Shifting to original place.");
recta.x = ori_x;
recta.y = ori_y;
}
}
}
Drag.active: dragArea1.drag.active
Drag.hotSpot.x: dragArea1.width / 2
Drag.hotSpot.y: dragArea1.height / 2
Drag.keys: ["origin"]
}
}
다른 방식으로 사용해보면 드래그해서 드롭하면 둘의 text가 서로 swap되게 만들 수 있게 됐다.
이게 어제 하루종일 구현해보고 싶었던 내용인데 하루 종일 해도 실패하다가 드디어 해냈다.
역시 결국은 구글과 스택오버플로우와 공식 도큐먼트다.
GPT와 코파일럿이 제 아무리 발전했다고 한들 어느정도 깊은 내용에 지엽적인 상황을 들이밀면 똑같은 말만 계속 되풀이한다.
결국 구글에서 스택오버플로우, qt forum을 보고 배우는게 훨씬 낫다
import QtQuick
import QtQuick.Controls
Window {
visible: true
width: 640
height: 480
Rectangle{
id: rectangle1
width: 100
height: 100
x: 0
y: 200
color: "blue"
Text{
id: text1
anchors.fill: parent
text: "BlueRect"
}
MouseArea {
id: dragArea1
anchors.fill: parent
drag.target: parent
acceptedButtons: Qt.AllButtons
property int ori_x
property int ori_y
onPressed: {
ori_x = rectangle1.x;
ori_y = rectangle1.y;
console.log(ori_x + ' ' + ori_y)
}
onReleased: {
if (parent.Drag.drop() !== Qt.IgnoreAction) {
console.log("drag in");
var temp = text1.text;
text1.text = text2.text;
text2.text = temp;
rectangle1.x = ori_x;
rectangle1.y = ori_y;
}
}
}
Drag.active: dragArea1.drag.active
Drag.hotSpot.x: dragArea1.width / 2
Drag.hotSpot.y: dragArea1.height / 2
DropArea {
id: dropArea1
anchors.fill: parent
onDropped: {
console.log("onDropped");
drop.accept()
}
}
}
Rectangle{
id: rectangle2
width: 100
height: 100
x: 200
y: 200
color: "red"
Text{
id: text2
anchors.fill: parent
text: "RedRect"
}
MouseArea {
id: dragArea2
anchors.fill: parent
drag.target: parent
acceptedButtons: Qt.AllButtons
property int ori_x
property int ori_y
onPressed: {
ori_x = rectangle2.x;
ori_y = rectangle2.y;
console.log(ori_x + ' ' + ori_y)
}
onReleased: {
if (parent.Drag.drop() !== Qt.IgnoreAction) {
console.log("drag in");
var temp = text1.text;
text1.text = text2.text;
text2.text = temp;
rectangle2.x = ori_x;
rectangle2.y = ori_y;
}
}
}
Drag.active: dragArea2.drag.active
Drag.hotSpot.x: dragArea2.width / 2
Drag.hotSpot.y: dragArea2.height / 2
DropArea {
id: dropArea2
anchors.fill: parent
onDropped: {
console.log("onDropped");
drop.accept()
}
}
}
}
이제 위의 두개의 코드를 잘 섞어서 TaskManager 프로젝트에 두 내용을 변경하게 만들 수 있을 듯하다.