在QML应用中如何实现drag and drop功能

在这篇文章中,我们将展示如何在QML应用中实现drag and drop的功能。更多的阅读可以参照Qt SDK。


在这里,我们首先设计一个DropTile.qml


DropTile.qml


import QtQuick 2.0

DropArea {
    id: dragTarget

    property string colorKey
    property alias dropProxy: dragTarget

    width: mainpage.width/4 - units.gu(1)
    height: width
    keys: [ colorKey ]

    onDropped: {
        console.log("onDropped!")
    }

    onEntered: {
        console.log("onEntered!");
    }

    onExited: {
        console.log("onExited!")
    }

    onPositionChanged: {
        console.log("onPositionChanged!");
    }

    Rectangle {       
        id: dropRectangle

        anchors.fill: parent
        color: colorKey

        states: [
            State {
                when: dragTarget.containsDrag
                PropertyChanges {
                    target: dropRectangle
                    color: "grey"
                }
            }
        ]
    }
}

代码的设计非常简单。处理显示一些events之外,只显示了一个Rectange。当有Drag存在时,显示的grey的颜色。否则为“colorKey”显示的颜色。

另外,我们设计一个DragTile.qml.

DragTile.qml


import QtQuick 2.0

Item {
    id: root
    property string colorKey

    width: mainpage.width/4 - units.gu(1); height: width

    MouseArea {
        id: mouseArea

        width: parent.width
        height: width

        anchors.centerIn: parent

        drag.target: tile

        onReleased: parent = tile.Drag.target !== null ? tile.Drag.target : root

        Rectangle {
            id: tile

            width: root.width; height: width
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter

            color: colorKey

            Drag.keys: [ colorKey ]
            Drag.active: mouseArea.drag.active
            Drag.hotSpot.x: 32
            Drag.hotSpot.y: 32

            Image {
                anchors.fill: parent
                source: image
            }

            states: State {
                when: mouseArea.drag.active
                ParentChange { target: tile; parent: root }
                AnchorChanges { target: tile; anchors.verticalCenter: undefined; anchors.horizontalCenter: undefined }
            }

        }
    }
}

在这个设计中,我们显示了一个图片。这个图片是在model中定义的。在mouseArea有drag实际时,我们有意地改变tile的父亲为root而不是先前的mouseArea。当鼠标在release时,如果有一个DropArea的话,它的地方将被自动放置root所展示的内容,在我们的示例中,也就是一个图片。


Main.qml


import QtQuick 2.4
import Ubuntu.Components 1.1

/*!
    \brief MainView with a Label and Button elements.
*/

MainView {
    // objectName for functional testing purposes (autopilot-qt5)
    objectName: "mainView"

    // Note! applicationName needs to match the "name" field of the click manifest
    applicationName: "draganddrop.liu-xiao-guo"

    /*
     This property enables the application to change orientation
     when the device is rotated. The default is false.
    */
    //automaticOrientation: true

    // Removes the old toolbar and enables new features of the new header.
//    useDeprecatedToolbar: false

    width: units.gu(60)
    height: units.gu(85)

    Page {
        id: mainpage
        title: i18n.tr("draganddrop")

        ListModel {
            id: mymodel
            ListElement {
                image: "images/pic1.jpg"
            }
            ListElement {
                image: "images/pic2.jpg"
            }
            ListElement {
                image: "images/pic3.jpg"
            }
            ListElement {
                image: "images/pic4.jpg"
            }
        }


        Column {
            id: layout
            anchors.centerIn: parent
            spacing: units.gu(5)

            Row {
                id: bottom
                width: bottom.childrenRect.width
                height: mainpage.height/3
                anchors.horizontalCenter: parent.horizontalCenter
                spacing: units.gu(1)

                Repeater {
                    model: mymodel.count;
                    delegate: DropTile { colorKey: "red" }
                }
            }

            Row {
                id: top
                width: top.childrenRect.width
                height: mainpage.height/3
                anchors.horizontalCenter: parent.horizontalCenter
                spacing: units.gu(1)

                Repeater {
                    model: mymodel
                    delegate: DragTile { colorKey: "red" }
                }
            }

        }
    }
}


在我们的Main.qml中,我们定义了一个model来装我们的数据,同时。我们创建了DragTile及DropTile。

运行我们的应用: