QML: how to move elements inside a grid

I have a 4x4 grid, and I want to associate arrow key presses with moving items inside the grid. How to do it?

Here is a QML example:

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

Update 1: Thanks to sebasgo and alexisdm for answers. If moving inside the grid is not so easy, why do we have a transition property move[http://qt-project.org/doc/qt-4.8/qml-grid.html#move-prop]

+5
source share
5 answers

It is better to use an element GridViewinstead of your approach Grid.

That way you can use the property currentIndexto choose which item to move as follows:

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;
}
+8
source

. . QML , , Grid x y. :

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

1:

( ) , , XmlListModel QAbstractItemModel.

move ( /) . , Grid .

, , , Grid .

+3

, , :

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;
}
0

, Qt 5.1 GridLayout :

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

GridView - . , , GRID. , . 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;
}
0

All Articles