【发布时间】:2016-09-26 16:32:41
【问题描述】:
我正在用 C++ 编写一个简单的 Snake 游戏,其中的游戏板模型包含一个二维状态向量 (std::vector<std::vector<board::state>>)。现在我想将这个棋盘暴露给 QML,这样它基本上就是某种可以访问模型状态的网格/棋盘。
我已经阅读了很多关于这个主题的内容,但仍然无法充分理解机制来解决我的问题。将文档、教程和博客条目应用于我的问题是我的障碍。
我为我的游戏板模型继承了QAbstractItemModel 并实现了必要的功能。现在我想进入 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)
board.cpp
#include "board.h"
board::board(int x, int y) :
m_board(x, std::vector<board::state>(y, board::state::empty))
{
}
//----------------------------------------------------------------------------------------------------------------------
board::state board::get_state(int x, int y) const
{
if((size_t) x >= m_board.size() || x < 0)
return board::state::empty;
if((size_t) y >= m_board.at(0).size() || y < 0)
return board::state::empty;
return m_board.at(x).at(y);
}
//----------------------------------------------------------------------------------------------------------------------
void board::set_state(int x, int y, state state)
{
if(get_state(x, y) == state)
return;
m_board.at(x).at(y) = state;
}
//----------------------------------------------------------------------------------------------------------------------
QModelIndex board::index(int row, int column, const QModelIndex&) const
{
if((size_t) row >= m_board.size() || row < 0)
return QModelIndex();
if((size_t) column >= m_board.at(0).size() || column < 0)
return QModelIndex();
return createIndex(row, column);
}
//----------------------------------------------------------------------------------------------------------------------
QModelIndex board::parent(const QModelIndex& index) const
{
if((size_t) index.row() >= m_board.size() || index.row() < 0)
return QModelIndex();
if((size_t) index.column() >= m_board.at(0).size() || index.column() < 0)
return QModelIndex();
return createIndex(index.row(), index.column());
}
//----------------------------------------------------------------------------------------------------------------------
int board::rowCount(const QModelIndex&) const
{
return m_board.size();
}
//----------------------------------------------------------------------------------------------------------------------
int board::columnCount(const QModelIndex&) const
{
return m_board.at(0).size();
}
//----------------------------------------------------------------------------------------------------------------------
QVariant board::data(const QModelIndex& index, int role) const
{
if(!index.isValid())
return QVariant();
if(role != Qt::DisplayRole)
return QVariant();
if((size_t) index.row() >= m_board.size() || index.row() < 0)
return QVariant();
if((size_t) index.column() >= m_board.at(0).size() || index.column() < 0)
return QVariant();
return qVariantFromValue(get_state(index.row(), index.column()));
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickView>
#include <board.h>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
board game_board(10, 10);
game_board.set_state(4, 9, board::state::snake);
game_board.set_state(3, 10, board::state::fruit);
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
QQmlContext *ctxt = view.rootContext();
ctxt->setContextProperty("myGameBoard", &game_board);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
main.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
}
}
}
我敢肯定,我遗漏了很多东西,或者是大错特错。此外,我知道将 C++ 模型暴露给 QML 是经常被问及的,并且得到了很好的覆盖,但我仍然无法管理。
陈述几个更具体的问题:
- 如何在 QML 中显示模型中的数据?我已经看到这是使用角色名称完成的,但我的行没有其列的角色名称
- 我的模型是否正确实施?
- 我需要使用什么 QML 组件来拥有棋盘/棋盘,如果我需要自定义组件,它需要哪些属性才能从模型中读取数据?
感谢观看!
【问题讨论】:
-
不投反对票或接近投票,因为我对 QML 一无所知,这对那些了解 QML 的人来说可能完全有意义,但我无法从上述问题陈述中挑选出问题陈述。您可能想要扩展或明确说明您的目标是什么以及附加的代码应该如何帮助实现目标,但没有
标签: c++ qt qml qtquick2 qt-quick