2012-08-31 9 views
5

Estoy siguiendo el enfoque dado en http://qt-project.org/wiki/Drag_and_Drop_within_a_GridView.QML: GridView con celdas móviles (arrastrar y soltar)

Tengo el programa presentado. Arrastrar y soltar funciona, pero después de la caída obtengo espacio vacío en mi cuadrícula. ¿Cómo puedo mejorar esto?

Además, también he notado que la función indexAt() en la línea 46 no funciona correctamente durante la operación de arrastre. Por lo tanto, tuve que agregar el cálculo explícito de gridArea.index.

(EDITADO) Me parece que aparece el espacio vacío porque después de dejar caer el elemento, vuelve a su posición original (está debajo del elemento visible). GridView no se actualiza y termina en un estado irregular.

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

Respuesta

4

Aquí, doy el código de trabajo. He agregado jerárquica adicional y coloqué Rectángulo en Artículo. Además, tuve que reparar Rectangle. Hay muchas soluciones similares disponibles, p. here.

En la solución dada, no hay ningún problema con la función indexAt() y por lo tanto el cálculo explícito de gridArea.index ya no es necesario.

Agradeceré cualquier comentario sobre esta solución y por qué estos cambios son tan importantes. Todavía creo que la solución original es intuitiva y no entiendo por qué no está funcionando .

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

Aquí hay otra respuesta usando la propiedad de arrastre de MouseArea. Es extraño, pero esta solución tiene problemas con la función indexAt(). Además, parece que no es posible agregar buenos efectos de cámara lenta usando Comportamiento en x e y.

Cualquier comentario sobre esta solución también es muy bienvenido.

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