【发布时间】:2020-01-26 07:19:28
【问题描述】:
我有一个相当复杂的 QML 组件和项目层次结构。 简而言之:
有一个父 GameGrid QML 类型可以做很多不同的事情。它可以做的事情取决于 GameGrid 当前处于什么状态。 GameGrid 的状态可以通过不同的函数来更改,具体取决于当前状态GameGrid。每当 GameGrid 更改状态时,它会自动触发处理该状态所有内容所需的代码。
有时,在更改状态时,由 GameGrid 运行的代码必须在完成处理后将 GameGrid 状态设置为不同的值。
-
这个操作的结果是:
:QML StateGroup:无法将状态更改应用为状态定义的一部分。
如何在“init”状态完成工作后解决此限制或正确进入“播放”状态?
我尝试过连接信号、函数和分配。
唯一可行的方法是使用一个单独的 Timer 项目,该项目之后会更改状态.. 这种方式过于复杂,无法在有许多状态和对这些状态的许多更改(有时是异步的)的大型代码库中实际实现。
这是重现此错误的最少代码
GameGrid.qml
import QtQuick 2.0
Item {
id: gameGrid
states: [
State {
name: "init"
StateChangeScript {
script: {
console.log("Init actions");
gameGrid.state = "play"; /* causes the error */
}
}
},
State {
name: "play"
StateChangeScript {
script: {
console.log("Play Actions"); /* never does actions */
}
}
}
]
Text {
anchors.centerIn: parent
text: parent.state
}
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
GameGrid {
id: grid
anchors.fill: parent
}
Component.onCompleted: {
grid.state = "init";
}
}
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
StateTest.pro
QT += quick
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp
RESOURCES += qml.qrc
QML_IMPORT_PATH =
QML_DESIGNER_IMPORT_PATH =
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
【问题讨论】: