2012-08-31 3 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를 추가하고 Rectangle을 Item에 넣습니다. 게다가, 나는 Rectangle을 reparent해야만했다. 사용 가능한 유사한 솔루션이 많이 있습니다 (예 : ). 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에 대한 Behavior를 사용하여 멋진 슬로우 모션 효과를 추가 할 수없는 것으로 보입니다.

이 솔루션에 대한 의견도 환영합니다.

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) 
      } 
     } 
    } 
}