2016-10-05 111 views
0

我需要在我的應用程序中繪製一堆矩形。用戶應該能夠單獨選擇它們並自由移動它們並改變它們的位置。用戶還應該能夠選擇多個矩形並同時移動所有選定的矩形並將其釋放到別的地方。 我已經可以實現基於Gridview的東西,它可以處理一個矩形的選擇和移動,但是我不能讓它適用於多個選擇/移動。以下是我目前使用的一段代碼:在Qml中拖放多個項目

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

我沒有設法讓您的代碼正常工作。首先,我看到它的錯誤:

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它可以工作,並且你只需在Rectangle中設置xy以將元素放在開頭。

現在,這是您的問題的解決方案:您單擊一個元素來選擇它,並且您可以一次移動所有選定的項目。

Window { 
    visible: true 
    width: 640 
    height: 480 

    property var totalZoneList: ["total1", "total2"] 
    property var moduleZoneList: ["module1", "module2"] 

    Repeater{ 
     id: iRepeater 
     model: ListModel { 
        id: myModel 
        function createModel() { 
         for(var i = 0; i < totalZoneList.length; i++) 
         { 
          for (var j = 0; j < moduleZoneList.length; j++) 
          { 
           myModel.append({"item1": totalZoneList[i], "item2": moduleZoneList[j]}) 
          } 
         } 
        } 
        Component.onCompleted: {createModel()} 
       } 
     delegate: myblocks 

    } 

    Component { 
     id: myblocks 

     Rectangle { 
      id: box 
      color: { 
       switch(index){ 
       case 0: selected ? "red" : "#FF9999";break; 
       case 1: selected ? "blue" : "lightblue";break; 
       case 2: selected ? "green" : "lightgreen";break; 
       case 3: selected ? "grey" : "lightgrey";break; 
       } 
      } 
      x: (width + 5)*index 

      width: 20 
      height: 20 
      property int offsetX:0 
      property int offsetY:0 
      property bool selected: false 
      function setRelative(pressedRect){ 
       disableDrag(); 
       x = Qt.binding(function(){ return pressedRect.x + offsetX; }) 
       y = Qt.binding(function(){ return pressedRect.y + offsetY; }) 
      } 
      function enableDrag(){ 
       gridArea.drag.target = box 
      } 
      function disableDrag(){ 
       gridArea.drag.target = null 
      } 

      MouseArea { 
       id: gridArea 
       anchors.fill: parent 
       hoverEnabled: true 
       drag.axis: Drag.XandYAxis 
       onClicked: parent.selected=!parent.selected 

       onPressed: { 

        var pressedRect = iRepeater.itemAt(index); 
        if (pressedRect.selected == true){ 
         for (var i=0; i<iRepeater.count; i++){ 
          var rect = iRepeater.itemAt(i); 
          if (i != index){ 
           //init for breaking existing binding 
           rect.x = rect.x 
           rect.y = rect.y 
           rect.disableDrag() 
           if (rect.selected == true){ 
            rect.offsetX = rect.x - pressedRect.x 
            rect.offsetY = rect.y - pressedRect.y 
            rect.setRelative(pressedRect) 
           } 
          } 
         } 
         pressedRect.enableDrag() 
        } 
       } 
      } // Mousearea 
     } // Rectangle 
    } // Component 
} 
+0

感謝您的回覆,但我不明白如何可以幫助移動多個項目。正如我所說,我不想移動所有的矩形。有時候只是其中的一個,有時也是其中的一個子集! –

+0

我已經測試過你的解決方案,它不起作用! –

+0

我編輯了帖子 – user2436719

1

配方一:

  1. 使用Repeater,所以定位不是由一個觀點,但自己決定。

  2. 使用隱形助手Item。這是你的drag.target

  3. 實現您的首選方式選擇您的對象 - 天氣通過單擊,或繪製框和執行檢查哪些對象包括在此框中。使所有選定對象的位置相對於您的隱形助手對象。

  4. 拖動輔助對象,並相應地移動所有其他對象。

  5. 完成後,再取消選擇對象,使它們的位置絕對(父母中的座標系)

配方二:

  1. 重新設置父級所有選擇的對象到一個新的項目,同時映射其座標

  2. 移動新項目

  3. 將所有對象重新繪製回原始畫布,並將其座標映射回原來的位置。


我希望這是足以解決你的問題(據我的理解是) 如果它解決了另一個問題,比你需要更具體的關於您的draged對象的預期行爲。