SCXML 媒体播放器

向 C++ 数据模型发送数据并接收它。

媒体播放器展示了如何从 C++ 数据模型中访问数据。数据模型允许为expr属性和<script>元素编写 C++ 代码。数据模型中的data部分由QScxmlCppDataModel的一个子类支持,Qt SCXML 编译器(qscxmlc)为它生成调度方法。

UI 是使用 Qt Quick 创建的。

运行示例

要从 Qt Creator 运行示例,请打开欢迎模式并从示例中选择示例。有关更多信息,请访问构建和运行示例

使用 C++ 数据模型

我们在 SCXML 文件中 <scxml> 元素的 datamodel 属性中指定数据模型

<scxml
    xmlns="http://www.w3.org/2005/07/scxml"
    version="1.0"
    name="MediaPlayerStateMachine"
    initial="stopped"
    datamodel="cplusplus:TheDataModel:thedatamodel.h"

datamodel 属性的格式为:cplusplus:<class-name>:<classdef-header>。因此,我们需要一个名为 thedatamodel.h 的文件,其中包含QScxmlCppDataModel的子类

#include "qscxmlcppdatamodel.h"
#include <QtQml/qqml.h>

class TheDataModel: public QScxmlCppDataModel
{
    Q_OBJECT
    Q_SCXML_DATAMODEL

QScxmlCppDataModelQObject 派生,所以我们把 Q_OBJECT 宏加在定义的私有部分,紧挨着开括号后。然后我们在 Q_OBJECT 后放置 Q_SCXML_DATAMODEL 宏。该宏展开为虚拟方法的声明,其实现由 Qt SCXML 编译器生成。

在 SCXML 文件中,我们在 <script> 元素中指定 C++ 语句,并使用 expr 属性访问数据模型

    <state id="stopped">
        <transition event="tap" cond="isValidMedia()" target="playing"/>
    </state>

    <state id="playing">
        <onentry>
            <script>
                media = eventData().value(QStringLiteral(&quot;media&quot;)).toString();
            </script>
            <send event="playbackStarted">
                <param name="media" expr="media"/>
            </send>
        </onentry>

        <onexit>
            <send event="playbackStopped">
                <param name="media" expr="media"/>
            </send>
        </onexit>

        <transition event="tap" cond="!isValidMedia() || media == eventData().value(QStringLiteral(&quot;media&quot;))" target="stopped"/>
        <transition event="tap" cond="isValidMedia() &amp;&amp; media != eventData().value(QStringLiteral(&quot;media&quot;))" target="playing"/>
    </state>

Qt SCXML 编译器在 mediaplayer.cpp 中的方法中生成了各种 evaluateTo 方法,并将表达式和脚本转换成其中的 lambda 表达式

bool TheDataModel::evaluateToBool(QScxmlExecutableContent::EvaluatorId id, bool *ok) {
....
    return [this]()->bool{ return isValidMedia(); }();
....
}

QVariant TheDataModel::evaluateToVariant(QScxmlExecutableContent::EvaluatorId id, bool *ok) {
....
        return [this]()->QVariant{ return media; }();
....
}

void TheDataModel::evaluateToVoid(QScxmlExecutableContent::EvaluatorId id, bool *ok) {
....
        [this]()->void{ media = eventData().value(QStringLiteral("media")).toString(); }();
....
}

示例项目 @ code.qt.io

© 2024 Qt 公司有限公司。此处包含的文档贡献的版权均为各自所有者的版权。本文件提供的文档受GNU 自由文档许可证版本 1.3的条款许可,该许可证由自由软件基金会发布。Qt 以及相应的标志是芬兰的 Qt 公司在全球的商标。所有其他商标均为其各自所有者的财产。