本页内容

SCXML 媒体播放器

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

媒体播放器,左侧显示歌曲列表,右侧显示“已停止”状态

媒体播放器演示了如何从 C++ 数据模型中访问数据。该数据模型支持编写针对expr属性和<script> 元素的 C++ 代码。数据模型的数据部分由QScxmlCppDataModel 的一个子类提供支持,Qt SCXML 编译器 (qscxmlc) 会为此生成分派方法。

用户界面使用Qt Quick 创建。

运行示例

您可以通过以下方式运行该示例:

使用 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

QScxmlCppDataModel 该类继承自 `QObject`,因此我们在定义的私有部分,紧跟在左括号之后添加 `Q_OBJECT ` 宏。随后,我们将 `Q_SCXML_DATAMODEL ` 宏置于 `Q_OBJECT` 之后。该宏展开为虚拟方法的声明,其实现由 `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 编译器会生成各种evaluateTo 方法,并将表达式和脚本转换为mediaplayer.cpp 中这些方法内的 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

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.