qml拖动交换之Gridview

qml拖动交换之Gridview

QML中mapToItem和mapFromItem的使用

坐标变换

在这里插入图片描述

代码

import QtQuick 2.6
import QtQuick.Window 2.2

Window {
    visible: true
    width: 1024
    height: 480
    title: qsTr("Drag Icon")

    property ListModel dataModel: ListModel {
        ListElement { title: qsTr("电话") }
        ListElement { title: qsTr("相册") }
        ListElement { title: qsTr("短信") }
        ListElement { title: qsTr("网络") }
        ListElement { title: qsTr("微信") }
        ListElement { title: qsTr("设置") }
        ListElement { title: qsTr("日历") }
        ListElement { title: qsTr("天气") }
        ListElement { title: qsTr("百度") }
        ListElement { title: qsTr("时间") }
        ListElement { title: qsTr("生活") }
    }

    QtObject {
        id: d

        readonly property int cellWidth: 128
        readonly property int cellHeight: 128
        readonly property int iconWidth: 96
        readonly property int iconHeight: 96

        property int dragIndex: -1
        property bool dragBehavior: false
    }

    GridView {
        id: gridView
        anchors.fill: parent
        cellWidth: d.cellWidth
        cellHeight: d.cellHeight
        move: Transition {
            NumberAnimation { properties: "x"; duration: 100; easing.type: Easing.OutCubic }
            NumberAnimation { properties: "y"; duration: 100; easing.type: Easing.OutCubic }
        }
        moveDisplaced: Transition {
            NumberAnimation { properties: "x"; duration: 300; easing.type: Easing.OutCubic}
            NumberAnimation { properties: "y"; duration: 100;  easing.type: Easing.OutCubic }
        }
        model: dataModel
        delegate: Item {
            width: d.cellWidth
            height: d.cellHeight
            z: mouseArea.pressed ? 1000 : 1
            Rectangle {
                id: btnIconArea
                anchors.centerIn: parent
                width: d.cellWidth
                height: d.cellWidth
                radius: 8
                border.width: 2
                border.color: "black"
                color:"blue"
                // color: "transparent"
                // border.color: "gray"
                Rectangle {
                    id: btnIcon
                    width: d.iconWidth
                    height: d.iconWidth
                    radius: 8
                    color: "grey"
                    border.color: "black"
                    Behavior on x { enabled: d.dragBehavior; NumberAnimation { duration: 200 } }
                    Behavior on y { enabled: d.dragBehavior; NumberAnimation { duration: 200 } }
                    Text {
                        anchors.centerIn: parent
                        color: "white"
                        text: model.title
                    }
                    MouseArea {
                        id: mouseArea
                        anchors.fill: parent
                        drag.target: parent
                        onPressed: {
                            d.dragBehavior = false;
                            var pos = gridView.mapFromItem(btnIcon, 0, 0);
                            console.log("onPressed pos : " + pos);
                            console.log("btnIcon.x: " + btnIcon.x+"btnIcon.y: "+btnIcon.y);
                            d.dragIndex = model.index;
                            btnIcon.parent = gridView;
                            btnIcon.x = pos.x
                            btnIcon.y = pos.y
                        }
                        onReleased: {
                            d.dragIndex = -1;
                            console.log("onReleased btnIcon.x : " + btnIcon.x + "btnIcon.y "+ btnIcon.y);
                            var pos = gridView.mapToItem(btnIconArea, btnIcon.x, btnIcon.y);
                            console.log("onReleased pos : " + pos);
                            console.log("btnIconArea.x: " + btnIconArea.x+"btnIconArea.y: "+btnIconArea.y);
                            // 这里一定要设置parent
                            btnIcon.parent = btnIconArea;
                            // 这几行代码是用来保证动画效果的
                            btnIcon.x = pos.x;
                            btnIcon.y = pos.y;
                            d.dragBehavior = true;
                            btnIcon.x = 0;
                            btnIcon.y = 0;
                        }

                        onPositionChanged: {
                            var pos = gridView.mapFromItem(btnIcon, 0, 0);
                            console.log("onPositionChanged pos :"+pos)
                            var idx = gridView.indexAt(pos.x, pos.y);
                            if (idx > -1 && idx < gridView.count) {
                                dataModel.move(d.dragIndex, idx, 1)
                                d.dragIndex = idx;
                            }

                        }
                    }
                }
            }
        }
    }


    Component.onCompleted: {
        console.log("gridView.spacing = " + gridView.spacing);
    }
}


用上面这个例子举例说明一下,拖动是怎么实现交换的。

我们应该是把A拖到B的时候,A拖到B需要我们自己实现,但是B回到A,或者回到其他地方,GridView会自动帮我们实现?movemoveDisplaced这两个动画需要我们实现。

pressed的时候,会记录当前对象btnIcon的索引dragIndex,同时将这个对象的parent设置为gridview

移动的时候,会不断触发onPositionChanged,将btnIcon对象的左上角坐标,转换成gridview下的坐标,根据这个坐标计算是在gridview中的哪一格,以此来判断是否需要交换。如果需要交换,就将之前记录的那个索引dragIndex对应的元素,移动到新的idx对应的元素那里。也就是说,这个时候,gridview中的元素已经完成了交换。我们拖动的是那个元素里面的一个子元素!

onReleased的时候,首先计算var pos = gridView.mapToItem(btnIconArea, btnIcon.x, btnIcon.y);这是btnIcon在btnIconArea中的相对位置,然后将btnIconparent换成btnIconArea,这一步很重要!!!

d.dragBehavior = true;用来保证动画时间

btnIcon.x = pos.x;
btnIcon.y = pos.y;来保证松开的时候,btnIcon坐标不会偏,然后再设置动画enable,再改变btnIcon坐标,展开一段动画效果。

// 这里一定要设置parent
btnIcon.parent = btnIconArea;
// 这几行代码是用来保证动画效果的
btnIcon.x = pos.x;
btnIcon.y = pos.y;
d.dragBehavior = true;
btnIcon.x = 0;
btnIcon.y = 0;

这里不理解的话,可以自己调试一下,就懂了。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值