QMLにおけるドラッグ&ドロップ
Drag & Drop on QML
QMLへDropAreaを組み込むことでドラッグ&ドロップを実装することができます。
[テキストやファイルのドロップ]
テキストやファイルなどのOSからのドロップであれば、DropAreaのenteredとdroppedシグナルでデータの受け入れを制御できます。
onEnteredではdragプロパティ(
DragEventタイプ)が使えます。対象がファイルなら「hasUrl」を、テキストなら「hasText」の値を調べ、条件に一致しないようであれば「drag.accepted = false;」とすることでデータのドロップを禁止します。
onDroppedではdropプロパティが使用できます。こちらも実体はDragEventなので「drop.text」などからデータを改めて取得します。
textdrop.qml
Rectangle {
x: 100
y: 210
width: 100
height: 100
color: "blue"
DropArea {
id: dta
anchors.fill: parent
onEntered:{
// drag.accepted = false;
}
onDropped:{
if (drop.hasUrls){
lbl.text = drop.urls.toString();
}else if (drop.hasText) {
lbl.text = drop.text;
}
}
}
}
[QMLアイテムのドラッグ&ドロップ]
QMLアイテムをドラッグできるようにするには、アイテムの「Drag.active」プロパティをtrueにします。Dragを有効にしてもマウス操作が使えるようになるわけではないので、MouseAreaを追加してドラッグさせたいアイテムと連動させる必要があります。
DropAreaで受け入れることのできるQMLアイテムを限定したいのであれば「keys」プロパティを使用します。DropAreaの「keys」配列内の文字列のいずれかと、ドラッグしたアイテムに含まれる「Drag.keys」配列内のいずれかが一致すると、ドロップ操作が受け入れられるようになります。
これらを踏まえたコード例がこちらになります。緑と青色の矩形は両方ともDropAreaですが、緑色にはkeysが指定されているので、ウィンドウにある赤色の矩形しかドラッグ&ドロップを受け付けません。
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Drag and Drop")
Text{
id: lbl
wrapMode: Text.Wrap
width: parent.width
text: "test"
}
DropArea {
id: da
x: 100
y: 100
width: 100
height: 100
Rectangle {
id: rc
anchors.fill: parent
color: "green"
}
// ドラッグキーに「test」を持つものだけを受け入れる
keys:["test"]
states: [
// ドラッグ&ドロップできるアイテムがあれば見た目を変えるようにする例
State{
when: da.containsDrag
PropertyChanges {
target: rc
color: "yellow"
}
}
]
}
Rectangle {
x: 100
y: 210
width: 100
height: 100
color: "blue"
DropArea {
id: dta
anchors.fill: parent
onEntered:{
// drag.accepted = false;
}
onDropped:{
if (drop.hasUrls){
lbl.text = drop.urls.toString();
}else if (drop.hasText) {
lbl.text = drop.text;
}
}
}
}
Rectangle {
x: 210
y: 100
width: 20
height: 20
color: "red"
Drag.active: true
Drag.keys: ["test"]
MouseArea {
anchors.fill: parent
// ドラッグを連動させたいアイテム
drag.target: parent
// ドラッグできるx方向の最小値と最大値
drag.minimumX: 100
drag.maximumX: 500
// QMLアイテムのドロップはMouseArea側で実装する必要がある
onReleased: {
if(parent.Drag.target === da){
lbl.text = "Dropped";
}
}
}
}
}
2018/11/02