Pregunta

Tengo una cuadrícula de 4x4 y quiero asociar las pulsaciones de las teclas de flecha con el movimiento de elementos dentro de la cuadrícula.¿Cómo se hace eso?

Aquí hay un QML de muestra:

import QtQuick 1.1

Rectangle {
    id: main;
    width: 500; height: 500;
    color: "darkgreen";

    property int emptyBlock: 16;

    Grid {
        id: grid16;
        x: 5; y: 5;
        width: 490; height: 490;
        rows: 4; columns: 4; spacing: 5;

        Repeater {
            model: 1;
            Rectangle {
                width: 118; height: 118; color: "darkblue";
            }
        }
    }

    Keys.onRightPressed: pressRight();

    function pressRight() {
        console.log("Left key pressed");
    }

    focus: true;
}

Actualización 1: Gracias a sebasgo y alexisdm por las respuestas.Si moverse dentro de una cuadrícula no es tan fácil, ¿por qué tenemos la move propiedad de transición [http://qt-project.org/doc/qt-4.8/qml-grid.html#move-prop]

¿Fue útil?

Solución

Será mejor que uses un GridView Artículo en lugar de tu Grid acercarse.

De esta manera puedes utilizarlo. currentIndex propiedad para elegir qué elemento mover de esta manera:

import QtQuick 1.1

Rectangle {
    id: main;
    width: 500; height: 500;
    color: "darkgreen";

    property int emptyBlock: 16;

    GridView {
        id: grid16;
        x: 5; y: 5;
        width: 490; height: 490;

        model: gridModel

        delegate: Component{
          Rectangle {
            width: 118; height: 118; color: "darkblue";
            Text {
              anchors.centerIn: parent
              font.pixelSize: 20
              text: value
            }
          }
        }
    }

    ListModel {
      id: gridModel
      ListElement {value: 1}
      ListElement {value: 2}
      ListElement {value: 3}
      ListElement {value: 4}
    }

    Keys.onRightPressed: {
      gridModel.move(grid16.currentIndex, grid16.currentIndex+1, 1)
    }

    Keys.onLeftPressed: {
      gridModel.move(grid16.currentIndex, grid16.currentIndex-1, 1)
    }

    focus: true;
}

Otros consejos

Las cuadrículas no le permiten manipular directamente la posición de los elementos contenidos.En cambio, su posición se deriva directamente del orden físico de los elementos secundarios de la cuadrícula.Hay no hay manera fácil para manipular elementos secundarios en QML dinámicamente, por lo que creo que deberías abandonar el Grid elemento y especifique la posición de los elementos secundarios explícitamente con el x y y propiedades.Aplicado a su código, esto podría verse así:

Rectangle {
    id: main;
    width: 500; height: 500;
    color: "darkgreen";

    Item {
        x: 5; y: 5;
        width: 490; height: 490;

        Repeater {
            id: pieces
            model: 1;
            Rectangle {
                property int column: 0
                property int row: 0
                x: column * 123
                y: row * 123
                width: 118; height: 118; color: "darkblue";
            }
        }
    }

    Keys.onRightPressed: pressRight();

    function pressRight() {
        console.log("Left key pressed");
        pieces.itemAt(0).column++
    }

    focus: true;
}

Actualización 1:

Las cuadrículas (en combinación con un repetidor) se pueden utilizar para visualizar modelos, por ejemplo, un XmlListModel artículo o un QAbstractItemModel descendiente.

Con move propiedad es fácil reaccionar a los cambios de diseño en el modelo (si se elimina/agrega una entrada) de forma animada.Aun así, los elementos del Grid se presentan estrictamente en el orden de las entradas del modelo.

Entonces, si desea tener control manual sobre la posición de sus artículos, incluso en el diseño celular, use un Grid no es aconsejable.

Puede cambiar el número de elementos antes del elemento que desea mover para cambiar su posición:

import QtQuick 1.1

Rectangle {
    id: main;
    width: 500; height: 500;
    color: "darkgreen";

    property int emptyBlock: 16;

    property int posX: 0;
    property int posY: 0;

    Grid {
        id: grid;
        x: 5; y: 5;
        width: 490; height: 490;
        rows: 4; columns: 4; spacing: 5;

        Repeater {
            id: beforeTheItem
            model: main.posX + parent.columns * main.posY
            Rectangle {
                width: 118; height: 118; color: "transparent";
            }
        }

        Rectangle {
            id:theItem
            width: 118; height: 118; color: "darkblue";
        }
    }

    Keys.onPressed: {
        // To avoid flickering, the item is hidden before the change
        // and made visible again after
        theItem.visible = false;
        switch(event.key) {
        case Qt.Key_Left: if(posX > 0) posX--;
            break;
        case Qt.Key_Right: if(posX < grid.columns - 1) posX++;
            break;
        case Qt.Key_Up: if(posY > 0) posY--;
            break;
        case Qt.Key_Down: if(posY < grid.rows - 1) posY++;
            break;
        }
        theItem.visible = true;
    }

    focus: true;
}

ahora, al usar qt 5.1 o superior y GridLayout Puede mover sus artículos sin problemas:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1

Window
{
    visible: true

    MainForm
    {
        GridLayout {
            id: gridLayout
            columns: 3

            property int oneRow: 0
            property int oneCol: 0

            Text { id: one; Layout.row :grid.oneRow; Layout.column: grid.oneCol; text: "My"; font.bold: true; }

            Text { text: "name"; color: "red" }
            Text { text: "is"; font.underline: true }
            Text { text: "not"; font.pixelSize: 20 }
            Text { text: "Ravan"; font.strikeout: true }
        }

        Component.onCompleted:
        {
            gridLayout.oneRow = 1
            gridLayout.oneCol = 2
        }
    }
}

El GridView es un monstruo muy confuso.Simplemente pongo una fila de un modelo dado, lo que conduce a la confusión, ya que se llama cuadrícula.Pero aún se puede usar como una cuadrícula de tamaño fijo, ya que me muestro en el siguiente ejemplo.Un solo cuadrado se puede mover con las teclas de flecha en una cuadrícula de 4x4.

    GridView {
        id: grid16;
        anchors.fill: parent
        cellWidth:  parent.width  / 2
        cellHeight: parent.height / 2

        model: gridModel

        delegate:
          Rectangle {
            Component.onCompleted: if( index >= 1 ) visible = false
            width: grid16.cellWidth ; height: grid16.cellHeight ; color: "yellow";
            Text {
              anchors.centerIn: parent
              font.pixelSize: 20
              text: value
            }
        }

        move: Transition {
            NumberAnimation { properties: "x,y"; duration: 1000 }
        }
    }

    ListModel {
      id: gridModel
      ListElement {value: 1}
      //Necessary, otherwise the grid will have the dimension 1x1
      ListElement {value: 2}
      ListElement {value: 3}
      ListElement {value: 4}
    }

    Keys.onRightPressed: { gridModel.move(grid16.currentIndex, grid16.currentIndex+1, 1) }
    Keys.onLeftPressed:  { gridModel.move(grid16.currentIndex, grid16.currentIndex-1, 1) }
    Keys.onUpPressed:    { gridModel.move(grid16.currentIndex, grid16.currentIndex-2, 1) }
    Keys.onDownPressed:  { gridModel.move(grid16.currentIndex, grid16.currentIndex+2, 1) }

    focus: true;
}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top