暴露2D C++;使用Qabstractemodel将游戏板转换为QML 我写了一个简单的蛇游戏,用C++中的一个游戏板模型来保存一个二维状态向量( STD::向量< /代码>)。现在我想把这个棋盘展示给QML,这样它基本上就是一个网格/棋盘,可以访问模型的状态。 关于这个话题我读了很多书,但仍然不能理解足够的力学来解决我的问题。将文档、教程和博客条目应用到我的问题上是我的障碍

暴露2D C++;使用Qabstractemodel将游戏板转换为QML 我写了一个简单的蛇游戏,用C++中的一个游戏板模型来保存一个二维状态向量( STD::向量< /代码>)。现在我想把这个棋盘展示给QML,这样它基本上就是一个网格/棋盘,可以访问模型的状态。 关于这个话题我读了很多书,但仍然不能理解足够的力学来解决我的问题。将文档、教程和博客条目应用到我的问题上是我的障碍,c++,qt,qml,qtquick2,qt-quick,C++,Qt,Qml,Qtquick2,Qt Quick,我为我的游戏板模型划分了qabstractemmodel子类,并实现了必要的功能。现在我想在QML中进行步骤,并在那里使用/显示我的模型的内容 这是我的密码: board.h #pragma once #include <vector> #include <QAbstractItemModel> class board : public QAbstractItemModel { Q_OBJECT public: enum class state {

我为我的游戏板模型划分了
qabstractemmodel
子类,并实现了必要的功能。现在我想在QML中进行步骤,并在那里使用/显示我的模型的内容

这是我的密码:

board.h

#pragma once

#include <vector>

#include <QAbstractItemModel>

class board : public QAbstractItemModel
{
  Q_OBJECT

public:
  enum class state
  {
    empty,
    snake,
    fruit
  };

  board(int x, int y);

  state get_state(int x, int y) const;
  void  set_state(int x, int y, state state);

  QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
  QModelIndex parent(const QModelIndex& index) const;
  int rowCount(const QModelIndex& parent = QModelIndex()) const;
  int columnCount(const QModelIndex& parent = QModelIndex()) const;
  QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;

private:
  std::vector<std::vector<state>> m_board;
};

Q_DECLARE_METATYPE(board::state)
我肯定有很多东西我遗漏了,或者完全错了。我也知道,经常把C++模型暴露给QML,并且经常被覆盖,但是我仍然无法处理。 陈述几个更具体的问题:

  • 如何在QML中显示模型中的数据?我看到这是通过角色名实现的,但我的行的列没有角色名
  • 我的模型正确实现了吗
  • 我需要使用什么QML组件才能拥有一个平铺/棋盘?如果我需要一个自定义组件,它需要哪些属性才能从模型中读取数据
谢谢你看

  • QtQuick是使用QML的主要UI框架,基本上只处理列表模型,因此在使用
    TableView

  • parent()
    方法是错误的,因为它基本上再次返回相同的索引。在您的案例中,这不会导致任何问题,因为您有一个表而不是一棵树

  • 建议:如果您只需要一个表模型,请从
    QAbstractTableModel
    派生,并让它负责
    index()
    parent()

  • 没有标准的QtQuick元素可以处理表模型,因此您要么构建自己的表模型,要么使用列表模型,只在网格中排列“列表项”
  • 对于自定义项,您可以构建一个与模型一起工作的项,甚至可以直接对数据工作,而不需要模型

    如果使用该模型并希望从QML实例化该模型,则需要“指向模型类的指针”或“指向
    qabstractemmodel
    的指针”属性

    如果您不想使用模型或不需要从QML实例化它,那么您根本不需要任何特定的属性

    在任何一种情况下,您的自定义项都可以使用以下方法之一:

  • 它可以自己绘制任何东西,即瓷砖网格和瓷砖本身
  • 只需提供网格并使用代理绘制不同类型的平铺,即,如
    ListView
    允许为列表元素、页眉、页脚等设置代理

  • 我有一个适合我的解决方案。以下是我所做的和一些代码:

    • 我使用Q_ENUM作为state ENUM,使其在QML中可用
    • 已将rootContext连接到QML引擎
    • 编写了一个自定义QML组件,该组件由一个列和一个中继器组成,该列包含一个行和一个中继器
    • 保存外部中继器和内部中继器的索引,以编译用于访问数据的索引
    • 一些清理
    代码

    Board.qml

    import QtQuick 2.6
    import QtQuick.Window 2.2
    
    Window {
      visible: true
    
      MouseArea {
        anchors.fill: parent
        onClicked: {
          Qt.quit();
        }
      }
    
      Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
      }
    
      GridView {
        model: myGameBoard
        delegate: Rectangle {
          width: 30
          height: 30
          color: blue
        }
      }
    }
    
    import QtQuick 2.0
    
    Column {
      Repeater {
        model: myGameBoard.columnCount()
    
        Row {
          property int y_pos: index
    
          Repeater {
            id: repeatr
            model: myGameBoard.rowCount()
    
            Cell {
              x_cord: index
              y_cord: y_pos
    
              size: 20
            }
          } //Repeater
        } //Row
      } //Repeater
    } //Column
    
    import QtQuick 2.0
    
    Rectangle {
      id: cell
      property int x_cord: 0
      property int y_cord: 0
      property int size: 10
    
      width: size
      height: size
    
      color: getCorrectColor()
    
      Connections {
        target: myGameBoard
        onDataChanged: {
          cell.color = cell.getCorrectColor()
        }
      }
    
      function getCorrectColor() {
        switch(myGameBoard.data(myGameBoard.index(cell.x_cord, cell.y_cord)) + 0) {
        case 0 :
          return "honeydew"
        case 1 :
          return "black"
        case 2 :
          return "orangered"
        default:
          return "yellow"
        }
      }
    }
    
    单元格.qml

    import QtQuick 2.6
    import QtQuick.Window 2.2
    
    Window {
      visible: true
    
      MouseArea {
        anchors.fill: parent
        onClicked: {
          Qt.quit();
        }
      }
    
      Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
      }
    
      GridView {
        model: myGameBoard
        delegate: Rectangle {
          width: 30
          height: 30
          color: blue
        }
      }
    }
    
    import QtQuick 2.0
    
    Column {
      Repeater {
        model: myGameBoard.columnCount()
    
        Row {
          property int y_pos: index
    
          Repeater {
            id: repeatr
            model: myGameBoard.rowCount()
    
            Cell {
              x_cord: index
              y_cord: y_pos
    
              size: 20
            }
          } //Repeater
        } //Row
      } //Repeater
    } //Column
    
    import QtQuick 2.0
    
    Rectangle {
      id: cell
      property int x_cord: 0
      property int y_cord: 0
      property int size: 10
    
      width: size
      height: size
    
      color: getCorrectColor()
    
      Connections {
        target: myGameBoard
        onDataChanged: {
          cell.color = cell.getCorrectColor()
        }
      }
    
      function getCorrectColor() {
        switch(myGameBoard.data(myGameBoard.index(cell.x_cord, cell.y_cord)) + 0) {
        case 0 :
          return "honeydew"
        case 1 :
          return "black"
        case 2 :
          return "orangered"
        default:
          return "yellow"
        }
      }
    }
    
    C++方面基本保持不变,除了在board.h上的state ENUM上使用Q_ENUM


    感谢您的帮助和对中继器的提示!

    不要投反对票或反对票,因为我对QML一无所知,这对那些了解QML的人来说可能是完全有意义的,但我很难从上面选择一个问题陈述。您可能想详细说明或明确说明您的目标是什么,以及所附代码应该如何提供帮助达到目标,但不感谢您的回答。我以前尝试过子类化
    QAbstractTableModel
    ,但遇到了这个问题,我只找到了在
    TableView
    中手动创建
    TableColumn
    s来使用它的方法。我的角色也有问题。我的目标是让QML显示我的两个硬币大小维度向量有10x10游戏板和50x50游戏板。问题是,我不知道如何使用角色来显示更多的单元格。我目前的理解是,表使用行,其中每个表上都有代表列的角色,但我不知道给单元格分配什么角色。正如我所说,QtQuick的元素不处理表模型,它们只列出模型并为单个列表项的不同方面使用角色。
    TableView
    类型可以直观地将不同方面映射到不同的列中。如果您想使用标准的QtQuick视图,我建议使用带有Repeater`的
    Grid'和从
    QAbstractListModel 。然后,模型还需要一个属性来指示一行中有多少项,然后在QML中使用此值来设置
    网格
    属性。即,一个一维数组,将块分组为列