代码之家  ›  专栏  ›  技术社区  ›  John

QML:如何使用拖放功能重新订购中继器项目?内部的一些工作代码

  •  0
  • John  · 技术社区  · 6 年前

    函数的作用是:创建表格并插入样本数据。“更改”按钮不会出现在最终代码中,我只是想用它来让重新排序的代码工作。

    import QtQuick.Controls 2.2 as QC2
    import QtQuick 2.10
    import QtQuick.Window 2.10
    import QtQuick.LocalStorage 2.0
    
    Window {
    id: root
    width: 320
    height: 480
    
    property var db
    property int rowHeight: 90
    
    Component.onCompleted: {
        db = LocalStorage.openDatabaseSync("test_db", "1.0", "Database", 100000)
        loadData()
    }
    
    property var sql_data: []
    
    function loadData() {
        var sql, rs, len, i
        db.transaction(function(tx) {
            tx.executeSql("DROP TABLE IF EXISTS tbl")
            tx.executeSql("CREATE TABLE IF NOT EXISTS tbl (
                rowId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL, listOrder INTEGER NOT NULL)")
            len = 5
            for (i = 0; i < len; i++)
                tx.executeSql("INSERT INTO tbl (name, listOrder) VALUES ('Item " + i + "', " + i + ")")
            rs = tx.executeSql("SELECT name, listOrder FROM tbl ORDER BY listOrder ASC")
        })
        len = rs.rows.length
        sql_data = new Array(len)
        for (i = 0; i < len; i++) {
            sql_data[i] = {"name": "", "order": ""}
            sql_data[i]["name"] = rs.rows.item(i).name
            sql_data[i]["order"] = rs.rows.item(i).listOrder
        }
        repeater.model = sql_data
    }
    
    Flickable {
        id: mainFlick
        anchors.fill: parent
        contentHeight: mainColumn.height
    
        Column {
            id: mainColumn
            width: parent.width
    
            QC2.Button {
                text: "Change"
                onClicked: {
                    var p1, p2
                    var d1 = new Date().getTime()
                    var movedEle = 3
                    var newPos = 1
                    var ele1 = repeater.itemAt(movedEle)
                    var ele2 = repeater.itemAt(newPos)
                    ele1.y = ele2.y
                    root.sql_data[movedEle]["order"] = root.sql_data[newPos]["order"]
                    if (newPos < movedEle) {
                        p1 = newPos
                        p2 = movedEle
                    } else {
                        p1 = movedEle
                        p2 = newPos
                    }
    
                    root.db.transaction(function(tx) {
                        var sql = "UPDATE tbl SET listOrder = " + root.sql_data[p1]["order"] + " "
                        sql += "WHERE listOrder = " + (root.sql_data[p2]["order"])
                        for (var i = p1; i < p2; i++) {
                            if (i !== movedEle) {
                                repeater.itemAt(i).y = repeater.itemAt(i).y + rowHeight
                                root.sql_data[i]["order"] += 1
                                sql = "UPDATE tbl SET listOrder = " + root.sql_data[i]["order"] + " "
                                sql += "WHERE listOrder = " + (root.sql_data[i]["order"] - 1)
                                tx.executeSql(sql)
                            }
                        }
                    })
                    sql_data = sql_data.sort(function(a,b) {
                        return a["order"] - b["order"]
                    })
                    repeater.model = sql_data
                    var d2 = new Date().getTime()
                    console.debug("Seconds: " + (d2 - d1) / 1000)
                }
            }
    
            Repeater {
                id: repeater
                width: parent.width
                model: []
                delegate: Column {
                    id: repeaterItem
                    width: parent.width - 20
                    height: rowHeight
                    anchors.horizontalCenter: parent.horizontalCenter
                    property int pos: index
    
                    DropArea {
                        id: dragTarget
                        width: parent.width
                        height: 20
    
                        Rectangle {
                            id: dropRect
                            anchors.fill: parent
                            color: "green"
                            states: [
                                State {
                                    when: dragTarget.containsDrag
                                    PropertyChanges {
                                        target: dropRect
                                        color: "red"
                                    }
                                }
    
                            ]
                        }
                    }
    
                    Row {
                        id: contentRow
                        width: parent.width
                        height: parent.height
                        z: 1
                        Column {
                            id: itemColumn
                            width: parent.width - 70
                            Text {
                                text: "Name: " + modelData["name"]
                            }
                            Text {
                                text: "Order: " + modelData["order"]
                            }
                            Text {
                                text: "Repeater Index: " + index
                            }
                        } // itemColumn
    
                        MouseArea {
                            id: dragArea
                            width: 40
                            height: itemColumn.height
    
                            drag.axis: Drag.YAxis
                            drag.target: dragRect
    
                            onReleased: parent = ((dragRect.Drag.target !== null) ? dragRect.Drag.target : root)
    
                            Rectangle {
                                Component.onCompleted: console.debug(dragRect.Drag.target)
                                id: dragRect
                                width: 40
                                height: itemColumn.height
                                color: "grey"
                                Drag.active: dragArea.drag.active
                                Drag.source: dragArea
                                Drag.hotSpot.x: width / 2
                                Drag.hotSpot.y: height / 2
                                states : State {
                                    when: dragArea.drag.active
                                    ParentChange { target: dragRect; parent: root }
                                    AnchorChanges {
                                        target: dragRect
                                        anchors.verticalCenter: undefined
                                        anchors.horizontalCenter: undefined
                                    }
                                }
                            }
                        }
                    } // contentRow
    
                    Behavior on y {
                        PropertyAnimation {
                            duration: 200
                            easing.type: Easing.Linear
                        }
                    }
                } // repeaterItem
            } // repeater
        } // mainColumn
    } // mainFlick
    } // id
    

    Qt Examples site .

    我的问题是:

    1. 如果我将拖动区域的目标从子矩形切换到整行(repeaterItem),则所有内容都将正常移动,但不再与拖放区域交互。
    2. 我想我可以在一行被拖拽之后,通过简单地得到拖拽区域的y值,得到新位置的索引。有没有更好的办法?

    因为“Change”按钮已经对行元素重新排序,

    1 回复  |  直到 6 年前
        1
  •  0
  •   John    6 年前

    这可能不是最有效的,但它是一个良好的开端,任何人都希望做类似的事情。

    import QtQuick.Controls 2.2 as QC2
    import QtQuick 2.10
    import QtQuick.Window 2.10
    import QtQuick.LocalStorage 2.0
    
    Window {
    id: root
    width: 320
    height: 580
    
    property var db
    property int rowHeight: 90
    property int len
    
    Component.onCompleted: {
        db = LocalStorage.openDatabaseSync("test_db", "1.0", "Database", 100000)
        loadData()
    }
    
    property var sql_data: []
    
    function loadData() {
        var sql, rs, i
        db.transaction(function(tx) {
            tx.executeSql("DROP TABLE IF EXISTS tbl")
            tx.executeSql("CREATE TABLE IF NOT EXISTS tbl (
                rowId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL, listOrder INTEGER NOT NULL)")
            len = 15
            for (i = 0; i < len; i++)
                tx.executeSql("INSERT INTO tbl (name, listOrder) VALUES ('Item " + i + "', " + i + ")")
            rs = tx.executeSql("SELECT name, listOrder FROM tbl ORDER BY listOrder ASC")
        })
        len = rs.rows.length
        sql_data = new Array(len)
        for (i = 0; i < len; i++) {
            sql_data[i] = {"name": "", "order": ""}
            sql_data[i]["name"] = rs.rows.item(i).name
            sql_data[i]["order"] = rs.rows.item(i).listOrder
        }
        repeater.model = sql_data
    }
    
    
    Flickable {
        id: mainFlick
        anchors.fill: parent
        contentHeight: mainColumn.height
        rebound: Transition {
            NumberAnimation {
                properties: "y"
                duration: 500
                easing.type: Easing.OutCirc
            }
        }
    
        Column {
            id: mainColumn
            width: parent.width
    
            function moveEle(start, end, f) {
                if (f === false) {
                    var p1, p2, ele1, ele2
                    var c = false
                    var d1 = new Date().getTime()
                    ele1 = repeater.itemAt(start)
                    console.debug(f)
                    ele2 = repeater.itemAt(end)
                    root.sql_data[start]["order"] = root.sql_data[end]["order"]
                    if (end < start) {
                        p1 = end
                        p2 = start
                    } else {
                        p1 = start
                        p2 = end
                        c = true
                    }
    
                    root.db.transaction(function(tx) {
                        var sql = "UPDATE tbl SET listOrder = " + root.sql_data[p1]["order"] + " "
                        sql += "WHERE listOrder = " + (root.sql_data[p2]["order"])
                        for (var i = p1; i < p2; i++) {
                            if (c === false) {
                                if (i !== start) {
                                    root.sql_data[i]["order"]++
                                    sql = "UPDATE tbl SET listOrder = " + root.sql_data[i]["order"] + " "
                                    sql += "WHERE listOrder = " + (root.sql_data[i]["order"] - 1)
                                    tx.executeSql(sql)
                                }
                            } else {
                                root.sql_data[i]["order"]--
                                sql = "UPDATE tbl SET listOrder = " + root.sql_data[i]["order"] + " "
                                sql += "WHERE listOrder = " + (root.sql_data[i]["order"] - 1)
                                tx.executeSql(sql)
                            }
                        }
                    })
                } else if (f === true) {
                    c = false
                    d1 = new Date().getTime()
                    ele1 = repeater.itemAt(start)
                    console.debug(f)
                    end--
                    ele2 = repeater.itemAt(end)
                    root.sql_data[start]["order"] = root.sql_data[end]["order"]
                    p1 = start
                    p2 = end
                    c = true
    
                    root.db.transaction(function(tx) {
                        var sql = "UPDATE tbl SET listOrder = " + root.sql_data[p1]["order"] + " "
                        sql += "WHERE listOrder = " + (root.sql_data[p2]["order"])
                        tx.executeSql(sql)
                        for (var i = p1; i <= p2; i++) {
                            if (i !== start) {
                                root.sql_data[i]["order"]--
                                sql = "UPDATE tbl SET listOrder = " + root.sql_data[i]["order"] + " "
                                sql += "WHERE listOrder = " + (root.sql_data[i]["order"] - 1)
                                tx.executeSql(sql)
                            }
                        }
                    })
                }
    
                sql_data = sql_data.sort(function(a,b) {
                    return a["order"] - b["order"]
                })
                repeater.model = sql_data
                var d2 = new Date().getTime()
                console.debug("Seconds: " + (d2 - d1) / 1000)
            }
    
            Repeater {
                id: repeater
                width: parent.width
                model: []
                delegate: Column {
                    id: repeaterItem
                    width: parent.width
                    height: rowHeight
                    anchors.horizontalCenter: parent.horizontalCenter
                    z: dragArea.drag.active ? 2 : 1
                    property int pos: index
    
                    DropArea {
                        id: dragTarget
                        width: parent.width
                        height: 15
                        property int ind: index
                        onEntered: {
                            drag.source.ind = index
                            drag.source.f = false
                            if (drag.source.ind !== drag.source.oldInd && drag.source.ind !== drag.source.oldInd + 1)
                                drag.source.caught = true
                        }
                        onExited: drag.source.caught = false
    
                        Rectangle {
                            id: dropRect
                            anchors.fill: parent
                            z: 0
                            states: [
                                State {
                                    when: dragTarget.containsDrag
                                    PropertyChanges {
                                        target: dropRect
                                        color: "grey"
                                    }
                                    PropertyChanges {
                                        target: dropRectLine
                                        visible: false
                                    }
                                }
                            ]
                            Rectangle {
                                id: dropRectLine
                                width: parent.width
                                height: 1
                                anchors.verticalCenter: parent.verticalCenter
                                color: "black"
                            }
                        }
                    }
                    Row {
                        id: contentRow
                        width: parent.width
                        height: parent.height
                        Drag.active: dragArea.drag.active
                        Drag.source: dragArea
                        Drag.hotSpot.x: width / 2
                        Drag.hotSpot.y: height / 2
                        Column {
                            id: itemColumn
                            width: parent.width - 70
                            Text {
                                text: "Name: " + modelData["name"]
                            }
                            Text {
                                text: "Order: " + modelData["order"]
                            }
                            Text {
                                text: "Repeater Index: " + index
                            }
                        } // itemColumn
    
                    MouseArea {
                        id: dragArea
                        width: 40 //repeater.width
                        height: itemColumn.height
    
                        drag.axis: Drag.YAxis
                        drag.target: contentRow
                        property point beginDrag
                        property point dropTarget
                        property bool caught: false
                        property int ind
                        property int oldInd: index
                        property bool f
                        onPressed: {
                            dragArea.beginDrag = Qt.point(contentRow.x, contentRow.y);
                        }
                        onReleased: {
                            if (dragArea.caught) {
                                dropRectFinal.color = "white"
                                dropRectLineFinal.visible = true
                                mainColumn.moveEle(index,dragArea.ind, dragArea.f)
                            } else {
                                backAnimY.from = contentRow.y;
                                backAnimY.to = beginDrag.y;
                                backAnim.start()
                            }
                        }
    
                            Rectangle {
                                id: dragRect
                                width: 40
                                height: itemColumn.height
                                color: "grey"
                            }
                        } // contentRow
                    } // dragArea
    
                    ParallelAnimation {
                        id: backAnim
                        SpringAnimation { id: backAnimY; target: contentRow; property: "y"; duration: 300; spring: 2; damping: 0.2 }
                    }
                } // repeaterItem
            } // repeater
    
            DropArea {
                id: dragTargetFinal
                width: parent.width
                height: 15
                property int ind: root.len
                onEntered: {
                    drag.source.ind = ind
                    drag.source.f = true
                    if (drag.source.ind !== drag.source.oldInd && drag.source.ind !== drag.source.oldInd + 1)
                        drag.source.caught = true
                }
                onExited: drag.source.caught = false
    
                Rectangle {
                    id: dropRectFinal
                    anchors.fill: parent
                    states: [
                        State {
                            when: dragTargetFinal.containsDrag
                            PropertyChanges {
                                target: dropRectFinal
                                color: "grey"
                            }
                            PropertyChanges {
                                target: dropRectLineFinal
                                visible: false
                            }
                        }
                    ]
                    Rectangle {
                        id: dropRectLineFinal
                        width: parent.width
                        height: 1
                        anchors.verticalCenter: parent.verticalCenter
                        color: "black"
                    }
                }
            }
        } // mainColumn
        QC2.ScrollBar.vertical: QC2.ScrollBar { active: scrollAnim.running ? true : false }
    } // mainFlick
    DropArea {
        id: scrollUp
        width: parent.width
        height: 50
        anchors.top: parent.top
        visible: {
            var visible = false
            if (mainFlick.contentY > 0)
                visible = true
            visible
        }
        onEntered: {
            scrollAnim.from = mainFlick.contentY
            scrollAnim.to = 0
            scrollAnim.start()
        }
        onExited: scrollAnim.stop()
    }
    DropArea {
        id: scrollDown
        width: parent.width
        height: 50
        anchors.bottom: parent.bottom
        visible: {
            var visible = false
            if (mainFlick.contentY < mainColumn.height - Window.height)
                visible = true
            visible
        }
        onEntered: {
            scrollAnim.from = mainFlick.contentY
            scrollAnim.to = mainColumn.height - Window.height
            scrollAnim.start()
        }
        onExited: scrollAnim.stop()
    }
    SmoothedAnimation {
        id: scrollAnim
        target: mainFlick
        property: "contentY"
        velocity: 400
        loops: 1
        maximumEasingTime: 10
    }
    } // root