在Qml中拖放多个项目

时间:2016-10-05 08:00:14

标签: qt drag-and-drop qml qtquick2 listmodel

我需要在我的应用程序中绘制一堆矩形。用户应该能够单独选择它们并自由移动它们并改变它们的位置。用户还应该能够选择多个矩形并同时移动所有选定的矩形并将其释放到其他位置。 我已经可以实现一些基于Gridview的东西,它可以处理一个Rectangle的选择和移动,但是我不能让它适用于多个选择/移动。这是我目前的一段代码:

GridView { 
        id: mainGrid
        cellWidth: 7;
        cellHeight: 7;

        ListModel {
            id: myModel
            function createModel() {
                for(var i = 0; i < totalZoneList.length; i++)
                {
                    for (var j = 0; j < moduleZoneList.length; j++)
                    {
                         myModel.append({"item1": ITEM1, "item2": ITEM2})
                    }
                }
            }
            Component.onCompleted: {createModel()}
        }

        Component { 
            id: myblocks
            Item {
                id: item
                width: mainGrid.cellWidth; 
                height: mainGrid.cellHeight;
                Rectangle {
                    id: box
                    parent: mainGrid
                    x: //CALCULATED BASED ON MODEL
                    y: //CALCULATED BASED ON MODEL
                    width: //CALCULATED BASED ON MODEL
                    height: //CALCULATED BASED ON MODEL


                    MouseArea {
                        id: gridArea
                        anchors.fill: parent
                        hoverEnabled: true
                        drag.axis: Drag.XandYAxis
                        drag.minimumX: 0
                        drag.minimumY: 0


                        property int mX: (mouseX < 0) ? 0 : ((mouseX < mainGrid.width - mainGrid.cellWidth) ? mouseX : mainGrid.width - mainGrid.cellWidth)
                        property int mY: (mouseY < 0) ? 0 : ((mouseY < mainGrid.height - mainGrid.cellHeight) ? mouseY : mainGrid.height - mainGrid.cellHeight)
                        property int index: parseInt(mX/mainGrid.cellWidth) + 5*parseInt(mY/mainGrid.cellHeight)  //item underneath cursor
                        property int activeIndex
                        property var xWhenPressed
                        property var yWhenPressed
                        propagateComposedEvents: true

                        onPressed: {
                            activeIndex = index
                            drag.target = box
                            xWhenPressed = box.x
                            yWhenPressed = box.y

                            gridArea.drag.maximumX = mainGrid.width - box.width
                            gridArea.drag.maximumY = mainGrid.height - box.height
                        }
                        onReleased: {
                           if(xWhenPressed !== box.x || yWhenPressed !== box.y)
                            {
                              //RECALCULATE THE POSITION
                            }
                        }
                        onPositionChanged: {
                            if (drag.active && index !== -1 && index !== activeIndex) {
                                                            mainGrid.model.move(activeIndex, activeIndex = index, 1)
                            }
                        }
                    } // Mousearea
                } // Rectangle
            } // Item
        } // Component

    } //mainGrid

2 个答案:

答案 0 :(得分:2)

我无法让您的代码正常运行。首先,我看到错误:

    <x:Array Type="{x:Type sys:Enum}">
        <local:DocumentTypes>First</local:DocumentTypes>
        <local:DocumentTypes>Second</local:DocumentTypes>
        <local:DocumentTypes>Third</local:DocumentTypes>
    </x:Array>

您只需要删除没有用的父Rectangle { id: box parent: mainGrid ... } ,并将Item设置为代理的根目录。

然后,你忘了提到拖拽的目标是Rectangle

Rectangle

以下是更正后的代码:

drag.target: parent

然后,您不应该使用Component { id: myblocks Rectangle { id: box color: "red" width: 20 height: 20 MouseArea { id: gridArea anchors.fill: parent drag.target: parent hoverEnabled: true drag.axis: Drag.XandYAxis } // Mousearea } // Rectangle } // Component ,因为您希望移动元素。如果您使用GridView它可以使用,则只需在Repeater中设置xy即可将元素放在开头。

现在这是您的问题的解决方案:您点击一个元素来选择它,您可以一次移动所有选定的项目。

Rectangle

答案 1 :(得分:1)

食谱一:

  1. 使用Repeater,因此定位不是由视图决定,而是由您自己确定。

  2. 使用隐形助手Item。这是您的drag.target

  3. 实施您选择对象的首选方式 - 通过点击天气或绘图框并检查此框中包含的对象。使所有选定对象的位置相对于不可见的辅助对象。

  4. 拖动辅助对象,并相应地移动所有其他对象。

  5. 完成后,再次取消选择对象并使其位置绝对(在父坐标系内)

  6. 食谱二:

    1. 将所有选定对象重新显示为新项目,同时相应地映射其坐标

    2. 移动新项目

    3. 将所有对象重新归还原始画布,将其坐标重新映射。

    4. 我希望这足以解决您的问题(据我所知) 如果它解决了另一个问题,那么你需要更加具体地说明拖曳物体的预期行为。