2014-09-25 39 views
3

我想使用ListView爲我的遊戲創建廣告資源用戶界面,其中的項目可以通過將其拖放到關卡中從庫存中刪除。如果物品沒有正確放置(仍在庫存中),則應將其放回到拖動之前的位置。使用ListView拖放來創建廣告資源UI

我已經得到了下面的代碼,但我不知道如何實現我之後的事情,即使在看完Drag and Drop example之後。

import QtQuick 2.3 

Rectangle { 
    id: root 
    width: 400 
    height: 400 

    ListView { 
     id: listView 
     width: parent.width/2 
     height: parent.height 

     model: ListModel { 
      Component.onCompleted: { 
       for (var i = 0; i < 10; ++i) { 
        append({value: i}); 
       } 
      } 
     } 

     delegate: Item { 
      id: delegateItem 
      width: listView.width 
      height: 50 

      Rectangle { 
       id: dragRect 
       width: listView.width 
       height: 50 
       anchors.horizontalCenter: parent.horizontalCenter 
       anchors.verticalCenter: parent.verticalCenter 
       color: "salmon" 
       border.color: Qt.darker(color) 

       Text { 
        anchors.centerIn: parent 
        text: modelData 
       } 

       MouseArea { 
        id: mouseArea 
        anchors.fill: parent 
        drag.target: dragRect 
       } 

       Drag.hotSpot.x: dragRect.width/2 
       Drag.hotSpot.y: dragRect.height/2 
      } 
     } 
    } 

    Rectangle { 
     width: parent.width/2 
     height: parent.height 
     anchors.right: parent.right 
     color: "#aaff0011" 

     DropArea { 
      id: dropArea 
      anchors.fill: parent 
     } 
    } 
} 

回答

6

您可以用下面的代碼實現這一點:

import QtQuick 2.3 

Rectangle { 
    id: root 
    width: 400 
    height: 400 

    ListView { 
     id: listView 
     width: parent.width/2 
     height: parent.height 

     property int dragItemIndex: -1 

     model: ListModel { 
      Component.onCompleted: { 
       for (var i = 0; i < 10; ++i) { 
        append({value: i}); 
       } 
      } 
     } 

     delegate: Item { 
      id: delegateItem 
      width: listView.width 
      height: 50 

      Rectangle { 
       id: dragRect 
       width: listView.width 
       height: 50 
       anchors.horizontalCenter: parent.horizontalCenter 
       anchors.verticalCenter: parent.verticalCenter 
       color: "salmon" 
       border.color: Qt.darker(color) 

       Text { 
        anchors.centerIn: parent 
        text: modelData 
       } 

       MouseArea { 
        id: mouseArea 
        anchors.fill: parent 
        drag.target: dragRect 

        drag.onActiveChanged: { 
         if (mouseArea.drag.active) { 
          listView.dragItemIndex = index; 
         } 
         dragRect.Drag.drop(); 
        } 
       } 

       states: [ 
        State { 
         when: dragRect.Drag.active 
         ParentChange { 
          target: dragRect 
          parent: root 
         } 

         AnchorChanges { 
          target: dragRect 
          anchors.horizontalCenter: undefined 
          anchors.verticalCenter: undefined 
         } 
        } 
       ] 

       Drag.active: mouseArea.drag.active 
       Drag.hotSpot.x: dragRect.width/2 
       Drag.hotSpot.y: dragRect.height/2 
      } 
     } 
    } 

    Rectangle { 
     width: parent.width/2 
     height: parent.height 
     anchors.right: parent.right 
     color: "#aaff0011" 

     DropArea { 
      id: dropArea 
      anchors.fill: parent 
      onDropped: { 
       listView.model.remove(listView.dragItemIndex); 
       listView.dragItemIndex = -1; 
      } 
     } 
    } 
} 

有些事情在這個例子中要注意:

  1. 我們存儲dragItemIndex,讓我們知道哪些項目被拖累。我們可以通過查看DropArea的drag.source屬性來實現同樣的功能,但是我們必須在委託中公開索引屬性,並且需要公開documentation discourages storing state in delegates

  2. 爲了實現「物品退回到拖曳不成功的地方」功能,我們讓dragRect成爲實際委託物品的孩子,以便它有一個父級可以堅持。如果我們沒有這樣做,那麼這個項目的父項就是ListView,如果不成功,它就會放在上次拖動的位置。

  3. 我們使用與Drag and Drop example相同的狀態改變行爲;拖動時,我們想從項目中移除錨點並讓它自由拖動。如果拖動失敗,狀態的when條件(dragRect.Drag.active)將變爲false,並且該項目會返回到尚未從列表視圖中的原始位置移動的委託項目。錨點也恢復了。這是各州的一個有用的功能;能夠隱式恢復以前的狀態。

  4. MouseAreadrag.onActiveChanged信號處理程序,我們稱之爲dragRect.Drag.drop(),使我們可以在DropArea該事件響應的onDropped信號處理程序,並刪除該項目。該項目被刪除後,我們將dragItemIndex重置爲無效索引。