如何从Qt的文档运行QML状态机示例?



在中断了几年之后,我最近又回到了Qt,看起来QML是这些天的"新热点"。过去,我设法从Qt的文档中获取基于小部件的示例,使其相对容易地工作,但是...现在我正在尝试学习 QML,我在缩小示例代码中的差距时遇到了麻烦。

具体来说,Qt.QmlStateMachine的文档说:

以下代码片段显示了单击按钮时将完成的状态机:

import QtQuick 2.0
import QtQml.StateMachine 1.0 as DSM
Rectangle {
Button {
anchors.fill: parent
id: button
text: "Finish state"
DSM.StateMachine {
id: stateMachine
initialState: state
running: true
DSM.State {
id: state
DSM.SignalTransition {
targetState: finalState
signal: button.clicked
}
}
DSM.FinalState {
id: finalState
}
onFinished: Qt.quit()
}
}
}

也许我完全天真,但我想我可以在 QtCreator 中创建一个新的Qt Quick应用程序并将上面的代码片段粘贴到main.qml中。但是,当我这样做时,我立即遇到一个错误,说:

QQmlApplicationEngine failed to load component
qrc:/main.qml:19 Button is not a type

所以。。。我查看了 QMLButton类型的文档,并注意到它在顶部附近显示:

导入语句:import QtQuick.Controls 1.4

因此,我将其添加到main.qml顶部,然后尝试再次运行。它"有效",但是...没有主窗口或任何其他视觉内容。嗯。我想我可以看到这(也许)有意义的地方,也许我不应该替换main.qml的全部内容?所以我决定尝试保留QtCreator提供的原始QML中的Window组件,将我的main.qml文件更改为如下所示:

import QtQuick 2.8                                                                                                                                                                                                                                            
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQml.StateMachine 1.0 as DSM
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
Button {
anchors.fill: parent
id: button
text: "Finish state"
DSM.StateMachine {
id: stateMachine
initialState: state
running: true
DSM.State {
id: state1
DSM.SignalTransition {
targetState: finalState
signal: button.clicked
}
}
DSM.FinalState {
id: finalState
}
onFinished: Qt.quit()
}
}
}
}

完成此操作后,我在运行时看到一个主窗口,但它是空的。嗯......不应该至少在某个地方有一个按钮吗?

无论如何,我不够聪明,在摆弄了将近90分钟之后,无法弄清楚这一点。Qt的文档作者似乎假设了我根本不具备的基本QML知识水平,所以我无法"填补空白"。这真的很遗憾,因为QML看起来很棒。我特别兴奋地看到我能用声明式状态机框架做什么!谁能告诉我这个特定的例子做错了什么?

(如果重要,我将Qt 5.9.2与QtCreator 4.4.1一起使用...

更新:在他的回答中,@eyllanesc指出了我上面发布的第二个代码片段中的一个小错别字。 我写id: state1的地方,应该是id: state的。

本文档假定对前面的主题和初始段落有一些基本知识: http://doc.qt.io/qt-5/qtqml-index.html 为您提供了您应该阅读和学习的主题列表。

像所有语言一样,人们必须阅读代码的错误并分析其逻辑。

...main.qml:17:13: QML StateMachine: No initial state set for StateMachine
QStateMachine::start: No initial state set for machine. Refusing to start.
.../main.qml:19: ReferenceError: state is not defined

此错误清楚地表明无法识别初始状态,这可能是由两个原因引起的,第一个是您尚未建立它,第二个是您建立了不适当的状态,在您的情况下是第二个原因。

您已经建立了初始状态:

initialState: state

但是状态不存在,我想你想放置状态1

initialState: state1

该按钮没有显示,因为您已经确定它的大小与父级的大小相同:anchors.fill: parent,并且Button的父级是Rectangle的,如果未设置Rectangle大小将具有 0,导致儿子也拥有它。一个可能的解决方案是建立父级大小的矩形:

import QtQuick 2.8                                                                                                                                                                                                                                            
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQml.StateMachine 1.0 as DSM
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
anchors.fill: parent
Button {
anchors.fill: parent
id: button
text: "Finish state"
DSM.StateMachine {
id: stateMachine
initialState: state1
running: true
DSM.State {
id: state1
DSM.SignalTransition {
targetState: finalState
signal: button.clicked
}
}
DSM.FinalState {
id: finalState
}
onFinished: Qt.quit()
}
}
}
}

或不使用矩形:

import QtQuick 2.8                                                                                                                                                                                                                                            
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQml.StateMachine 1.0 as DSM
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Button {
anchors.fill: parent
id: button
text: "Finish state"
DSM.StateMachine {
id: stateMachine
initialState: state1
running: true
DSM.State {
id: state1
DSM.SignalTransition {
targetState: finalState
signal: button.clicked
}
}
DSM.FinalState {
id: finalState
}
onFinished: Qt.quit()
}
}
}

最新更新