2012-08-31 43 views
5

我遵循http://qt-project.org/wiki/Drag_and_Drop_within_a_GridView上给出的方法。QML:带可移动单元格的GridView(拖放)

我有介绍的程序。拖放正在工作,但在放下后,我的网格中会有空的空间 。我该如何改进?

此外,我还注意到,拖动操作过程中,第46行中的函数indexAt()无法正常工作。因此我不得不添加gridArea.index的明确计算。

(EDITED)在我看来,空的空间出现的原因是,在放下元素后,它返回到原来的位置(它在可见元素下面)。 GridView没有更新并且以不规则的状态完成。

import QtQuick 1.1 

GridView { 
    id: mainGrid 
    cellWidth: 165; cellHeight: 95 
    width: 5*cellWidth; height: 4*cellHeight 
    model: myModel 
    delegate: myButton 

    ListModel { 
     id: myModel 
     function createModel() { 
      for (var i=1; i<=20; i++) { 
       myModel.append({"display": i, "uid": i}) 
      } 
     } 
     Component.onCompleted: {createModel()} 
    } 

    Component { 
     id: myButton 
     Rectangle { 
      id: item 
      width: mainGrid.cellWidth-5; height: mainGrid.cellHeight-5; 
      border.width: 1 
      property int uid: (index >= 0) ? myModel.get(index).uid : -1 
      Text { 
       anchors.centerIn: parent 
       text: display 
       font.pixelSize: 48 
      } 
      states: [ 
       State { 
        name: "active"; when: gridArea.activeId == item.uid 
        PropertyChanges {target: item; x: gridArea.mouseX-80; y: gridArea.mouseY-45; z: 10; smooth: false} 
       } 
      ] 
     } 
    } 

    MouseArea { 
     id: gridArea 
     anchors.fill: parent 
     hoverEnabled: true 
     preventStealing : true 
     //property int index: mainGrid.indexAt(mouseX, mouseY) //WHY IS THIS NOT WORKING RELIABLE? 
     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 activeId: -1 //uid of active item 
     property int activeIndex //current position of active item 
     onPressAndHold: { 
      activeId = mainGrid.model.get(activeIndex=index).uid 
     } 
     onReleased: { 
      activeId = -1 
     } 
     onPositionChanged: { 
      if (activeId != -1 && index != -1 && index != activeIndex) { 
       mainGrid.model.move(activeIndex, activeIndex = index, 1) 
      } 
     } 
    } 
} 

回答

4

在这里,我给出了工作代码。我添加了额外的hiearchy并将矩形放入Item中。而且,我不得不重置Rectangle。有许多类似的解决方案,例如 ,例如here

在给定的解决方案中,函数indexAt()没有问题,因此不再需要显式计算gridArea.index。

对于这个解决方案以及为什么这些改变如此重要,我将不胜感激。 我仍然认为原来的解决方案是直观的,我不明白为什么它是 无法正常工作。

import QtQuick 1.1 

GridView { 
    id: mainGrid 
    cellWidth: 165; cellHeight: 95 
    width: 5*cellWidth; height: 4*cellHeight 
    model: myModel 
    delegate: myButton 

    ListModel { 
     id: myModel 
     function createModel() { 
      for (var i=1; i<=20; i++) { 
       myModel.append({"display": i, "uid": i}) 
      } 
     } 
     Component.onCompleted: {createModel()} 
    } 

    Component { 
     id: myButton 
     Item { 
      id: item 
      width: mainGrid.cellWidth-5; height: mainGrid.cellHeight-5; 
      Rectangle { 
       id: box 
       parent: mainGrid 
       x: item.x; y: item.y; 
       width: item.width; height: item.height; 
       border.width: 1 
       property int uid: (index >= 0) ? myModel.get(index).uid : -1 
       Text { 
        anchors.centerIn: parent 
        text: display 
        font.pixelSize: 48 
       } 
       states: [ 
        State { 
         name: "active"; when: gridArea.activeId == box.uid 
         PropertyChanges {target: box; x: gridArea.mouseX-80; y: gridArea.mouseY-45; z: 10} 
        } 
       ] 
      } 
     } 
    } 

    MouseArea { 
     id: gridArea 
     anchors.fill: parent 
     hoverEnabled: true 
     preventStealing : true 
     property int index: mainGrid.indexAt(mouseX, mouseY) //item underneath cursor 
     property int activeId: -1 //uid of active item 
     property int activeIndex //current position of active item 

     onPressAndHold: { 
      activeId = mainGrid.model.get(activeIndex=index).uid 
     } 
     onReleased: { 
      activeId = -1 
     } 
     onPositionChanged: { 
      if (activeId != -1 && index != -1 && index != activeIndex) { 
       mainGrid.model.move(activeIndex, activeIndex = index, 1) 
      } 
     } 
    } 
} 
1

这是使用MouseArea的drag属性的另一个答案。它很奇怪,但是这个解决方案在函数indexAt()方面有问题。而且,用x和y上的行为来添加漂亮的慢动作效果似乎是不可能的。

对此解决方案的任何评论也非常受欢迎。

import QtQuick 1.1 

GridView { 
    id: mainGrid 
    cellWidth: 165; cellHeight: 95 
    width: 5*cellWidth; height: 4*cellHeight 
    model: myModel 
    delegate: myButton 

    ListModel { 
     id: myModel 
     function createModel() { 
      for (var i=1; i<=20; i++) { 
       myModel.append({"display": i}) 
      } 
     } 
     Component.onCompleted: {createModel()} 
    } 

    Component { 
     id: myButton 
     Rectangle { 
      id: item 
      z: 1 
      width: mainGrid.cellWidth-5; height: mainGrid.cellHeight-5; 
      border.width: 1 
      Text { 
       anchors.centerIn: parent 
       text: display 
       font.pixelSize: 48 
      } 
     } 
    } 

    MouseArea { 
     id: gridArea 
     anchors.fill: parent 
     hoverEnabled: true 
     drag.axis: Drag.XandYAxis 
     //property int index: mainGrid.indexAt(mouseX,mouseY) //NOT WORKING RELIABLE! 
     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 

     onPressAndHold: { 
      currentIndex = index 
      currentItem.z = 10 
      gridArea.drag.target = currentItem 
      activeIndex = index 
     } 
     onReleased: { 
      currentItem.x = mainGrid.cellWidth * (index % 5) 
      currentItem.y = mainGrid.cellHeight * parseInt(index/5) 
      currentItem.z = 1 
      currentIndex = -1 
      gridArea.drag.target = null 
     } 
     onPositionChanged: { 
      if (drag.active && index !== -1 && index !== activeIndex) { 
       mainGrid.model.move(activeIndex, activeIndex = index, 1) 
      } 
     } 
    } 
}