如何从Qt的文档中运行QML StateMachine示例?

时间:2017-12-31 20:51:42

标签: qt qml qt5

我在最近几年的间隙后回到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

所以...我查看了QML Button type的文档,并注意到它位于顶部附近:

  

导入声明: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

1 个答案:

答案 0 :(得分:1)

本文档假定您对以前主题和初始段落有一些基本了解: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

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

您已建立初始状态:

initialState: state

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

initialState: state1

此按钮未显示,因为您已确定其大小与父级的大小相同:anchors.fill: parent,而Button的父级是Rectangle,并且如果未设置Rectangle,则大小将为0,导致儿子也拥有它。一种可能的解决方案是将Rectangle设置为父级的大小:

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()
            }
        }
    }
}

或不使用Rectangle:

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()
        }
    }
}