У меня есть настольная игра с пронумерованными плитками, расположенными в квадратной сетке. Доска использует GridView с пользовательской моделью GameBoard (GameBoardModel, экспортированной в QML), унаследованной от QAbstractListModel. В стандартной форме игра использует сетку плиток 4x4, потому что именно столько (16) плиток создает конструктор модели по умолчанию. Однако я подумал сделать что-то вроде выпадающего списка, который бы позволял выбирать размер доски, который затем будет сгенерирован и игра начнется.
Теперь проблема в том, что я не вижу очевидный способ отправить число (или вызвать функцию) из QML, который приступит к созданию модели с желаемыми параметрами, загрузит ее в QML и обновит представление.
Я пробовал создать отдельную кнопку и используя свойство dimension моей модели, чтобы установить для размера новое значение с помощью onClicked MouseArea и написать _gameboard .model.dimension = 5 (где _gameboard — это id типа GameBoard QML, который использует GameBoardModel), но я так и не смог понять, как правильно обновить свою модель. Я попытался создать своего рода метод reloadModel, который по сути создает новый список плиток с новыми номерами и который будет вызываться после каждого обновления размера, но даже после вызова dataChanged отображалось только старое количество элементов, равное 16, а не 25 (не считая одного, намеренно скрытого).
C++< /p>
part of gameboard.h
class GameBoard : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int dimension READ dimension WRITE setDimension NOTIFY dimensionChanged)
Q_PROPERTY(int hiddenElementValue READ boardSize NOTIFY hiddenElementChanged)
public:
static constexpr size_t defaultPuzzleDimension = 4;
GameBoard(QObject* parent = nullptr, const size_t boardDimension = defaultPuzzleDimension);
size_t dimension() const;
void setDimension(size_t newDimension);
size_t boardSize() const;
signals:
void dimensionChanged(const size_t newDimension);
void hiddenElementChanged(int newHiddenElementValue);
private:
std::vector m_rawBoard;
size_t m_dimension;
size_t m_boardSize;
void reloadModel();
}
part of gameboard.cpp
size_t GameBoard::dimension() const
{
return m_dimension;
}
void GameBoard::setDimension(size_t newDimension)
{
m_dimension = newDimension;
reloadModel();
emit dimensionChanged(m_dimension);
emit hiddenElementChanged(m_boardSize);
}
size_t GameBoard::boardSize() const
{
return m_boardSize;
}
void GameBoard::reloadModel()
{
m_rawBoard.clear();
m_boardSize = m_dimension * m_dimension;
m_rawBoard.resize(m_boardSize);
std::iota(m_rawBoard.begin(),m_rawBoard.end(),1);
shuffle();
dataChanged(createIndex(0,0),createIndex(m_boardSize,0));
}
QML
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
id: root
width: 680
height: 440
visible: true
title: qsTr("Hello World")
Item {
id: _firstTile
width: 0.5 * root.width
height: 0.1 * root.height
anchors.horizontalCenter: parent.horizontalCenter
Tile {
radius: 30
anchors.fill: parent
anchors.topMargin: 0.05 * parent.height
anchors.bottomMargin: 0.05 * parent.height
MouseArea {
anchors.fill: parent
onClicked: {
_gameboard.model.dimension = 5;
}
}
}
}
Item {
width: root.width
height: 0.9 * root.height
anchors.top: _firstTile.bottom
GameBoard {
id: _gameboard
anchors.fill: parent
}
}
}
GameBoard.qml
import QtQuick 2.0
import Game 1.0
GridView {
id: root
model: GameBoardModel {
}
cellHeight: height / root.model.dimension
cellWidth: width / root.model.dimension
delegate: Item {
id: _backgroundDelegate
width: root.cellWidth
height: root.cellHeight
visible: display != root.model.hiddenElementValue
Tile {
displayText: display
anchors.fill: _backgroundDelegate
anchors.margins: 3
MouseArea {
anchors.fill: parent
onClicked: {
root.model.move(index);
}
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/784 ... parameters