Qt QML:如何在网格中移动项目

Qt QML:如何在网格中移动项目,qt,grid,qml,qt-quick,Qt,Grid,Qml,Qt Quick,我有一个4x4网格,我想将箭头键按下与网格内项目的移动相关联。你是怎么做到的 以下是一个示例QML: 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:

我有一个4x4网格,我想将箭头键按下与网格内项目的移动相关联。你是怎么做到的

以下是一个示例QML:

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

更新1:感谢sebasgo和Alexism的回答。如果在网格中移动不是那么容易,那么为什么我们有
move
transition属性[http://qt-project.org/doc/qt-4.8/qml-grid.html#move-prop]

栅格无法直接操纵所包含项目的位置。相反,它们的位置直接来自网格子项的物理顺序。QML中需要动态操作子项,因此我认为您应该放弃
网格
项,并使用
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
项或
qabstractemmodel
子项

使用
move
属性,可以轻松地以动画方式对模型中的布局更改做出反应(如果删除/添加了条目)。尽管如此,
表格中的项目仍然严格按照模型条目的顺序排列


因此,如果您想要手动控制项目的位置,即使在蜂窝布局中,也不建议使用
网格

您可以在要移动的项目之前更改项目的数量以更改其位置:

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;
}
导入QtQuick 1.1
长方形{
id:main;
宽度:500;高度:500;
颜色:“暗绿色”;
属性int emptyBlock:16;
属性int posX:0;
属性int posY:0;
网格{
id:网格;
x:5;y:5;
宽度:490;高度:490;
行:4;列:4;间距:5;
中继器{
身份证号码:beforeitem
型号:main.posX+parent.columns*main.posY
长方形{
宽度:118;高度:118;颜色:“透明”;
}
}
长方形{
id:Iteem
宽度:118;高度:118;颜色:“深蓝色”;
}
}
按键。ON按下:{
//为避免闪烁,在更改之前将隐藏该项
//之后又出现了
可见=假;
开关(事件键){
案例Qt.Key_左:如果(posX>0)posX--;
打破
case Qt.Key_Right:if(posX0)posY--;
打破
case Qt.Key_Down:if(posY
您最好使用
网格视图
项,而不是
网格
方法

通过这种方式,您可以使用它的
currentIndex
属性选择要移动的项目,如下所示:

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;
}
现在,通过使用或以上选项,您可以轻松移动物品:

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

GridView是一个非常令人困惑的怪物。它只填充给定模型中的一行,这会导致混淆,因为它被称为网格。但它仍然可以用作固定大小的网格,如下面的示例所示。在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;
}

要更新1,请参见下面的示例,其中可以在4x4大小的网格上移动项目。GridLayout不支持模型。如果您使用的是更大的网格,那么您肯定想要使用模型,并且需要切换到GridView。使用转发器来使用模型。在网格布局中移动项目似乎更容易