使用Qt Creator创建和编辑状态图详细教程

使用Qt Creator创建和编辑状态图详细教程

一、使用Qt Creator创建和编辑状态图

1、创建新项目



2、新建scxml文件



3、编辑状态图实现下面这个状态

xml 复制代码
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="MainControl">
    <!-- 主控制状态 -->
    <state id="MainControl">
        <initial>
            <transition target="Stopped"/>
        </initial>
        
        <!-- 设备停止状态 -->
        <state id="Stopped">
            <onentry>
                <log expr="'设备已停止'"/>
            </onentry>
            <transition event="start" target="Running"/>
        </state>

        <!-- 设备运行状态 -->
        <state id="Running" initial="Preparing">
            <onentry>
                <log expr="'设备启动中...'"/>
            </onentry>
            
            <!-- 准备阶段 -->
            <state id="Preparing">
                <transition event="ready" target="Working"/>
            </state>

            <!-- 工作阶段 -->
            <state id="Working">
                <transition event="emergency.stop" target="Stopped"/>
                <transition event="pause" target="Paused"/>
            </state>

            <!-- 暂停状态 -->
            <state id="Paused">
                <transition event="resume" target="Working"/>
                <transition event="emergency.stop" target="Stopped"/>
            </state>
        </state>
    </state>

    <!-- 并行电池监控状态 -->
    <parallel id="BatteryMonitor">
        <state id="Normal">
            <transition cond="BatteryLevel &lt; 20" target="LowBattery"/>
        </state>
        <state id="LowBattery">
            <onentry>
                <log expr="'警告:电量不足!'"/>
            </onentry>
            <transition cond="BatteryLevel &gt;= 20" target="Normal"/>
        </state>
    </parallel>

    <!-- 全局事件处理 -->
    <transition event="system.shutdown" target="Shutdown"/>
    <final id="Shutdown">
        <onentry>
            <log expr="'系统关闭'"/>
        </onentry>
    </final>
</scxml>

单击状态会出现箭头

绘制完成

查看结果:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" binding="early" xmlns:qt="http://www.qt.io/2015/02/scxml-ext" name="MainControl" qt:editorversion="18.0.0" initial="Stopped">
    <qt:editorinfo initialGeometry="221.80;107.85;-20;-20;40;40"/>
    <state id="Stopped">
        <qt:editorinfo scenegeometry="535.18;129.21;475.18;79.21;120;100" geometry="535.18;129.21;-60;-50;120;100"/>
        <transition type="external" event="start" target="Running"/>
    </state>
    <state id="Running">
        <qt:editorinfo scenegeometry="419.70;326.60;-174.47;359.95;1419.29;255.59" geometry="419.70;326.60;-594.16;33.35;1419.29;255.59"/>
        <state id="Preparing">
            <qt:editorinfo scenegeometry="383.59;291.38;323.59;241.38;120;100" geometry="-490.41;161.15;-60;-50;120;100"/>
            <transition type="external" event="ready" target="Working"/>
        </state>
        <state id="Working">
            <qt:editorinfo scenegeometry="471.49;487.75;411.49;437.75;120;100" geometry="51.79;161.15;-60;-50;120;100"/>
            <transition type="external" event="pause" target="Paused"/>
        </state>
        <state id="Paused">
            <qt:editorinfo scenegeometry="1616.74;291.38;1556.74;241.38;120;100" geometry="742.74;161.15;-60;-50;120;100"/>
            <transition type="external" event="resume" target="Working"/>
        </state>
    </state>
</scxml>

其余自己添加

二、如何使用状态图

参考我这篇文档:Qt SCXML 模块详解

三、Qt SCXML 模块详解

1、SCXML 概述

SCXML (State Chart XML) 是一种基于 XML 的 W3C 标准,用于描述复杂的状态机(State Machines)。它提供了一种形式化的方式来定义:

  • 状态(States):如 初始状态最终状态复合状态(包含子状态)、并行状态
  • 转换(Transitions):状态之间的迁移路径,由 事件 触发,并可带有 条件执行的动作
  • 事件(Events):触发状态转换的信号。
  • 动作(Actions):在进入/退出状态或执行转换时执行的逻辑,如发送事件、调用脚本、操作数据模型等。
  • 数据模型(Data Model):用于存储状态机上下文相关的数据。

2、Qt SCXML 模块的作用

Qt 的 SCXML 模块 (QtSCXML) 提供了在 Qt 应用程序中使用 SCXML 标准的能力。其主要组件包括:

  • QScxmlStateMachine :核心类,代表一个 SCXML 状态机实例。它:
    • 解析 SCXML 文件或字符串。
    • 管理状态机的生命周期(初始化、启动、停止)。
    • 提供接口与状态机交互:发送事件、查询当前状态、订阅状态变化通知等。
    • 可以与 Qt 的信号/槽机制集成。
  • SCXML 编译器 (qscxmlc) :一个命令行工具(或可通过 CMake/QMake 集成),用于将 SCXML 文件编译成 C++ 代码(.h.cpp 文件)。
    • 目的:提升运行时性能(避免 XML 解析开销)和类型安全性(生成的类提供事件类型和属性访问器)。
    • 生成内容 :一个继承自 QScxmlStateMachine 的特定状态机类。该类:
      • 提供强类型的事件发送方法(如 submitEventName() 代替通用的 submitEvent("EventName"))。
      • 提供访问 SCXML 数据模型中定义的数据属性的方法(如 property() 或生成的 getter/setter)。
      • 为每个状态定义了枚举常量(便于查询当前状态)。
  • Qt 状态机集成 :虽然 SCXML 本身功能强大,但 QScxmlStateMachine 可以无缝地与 Qt 的事件循环和对象系统协作。

3、使用 Qt SCXML 模块的基本步骤

3.1 编写 SCXML 文件

使用文本编辑器或专门的 SCXML 编辑器(如 qscxml 提供的 qscxmlmon)创建描述状态机的 .scxml 文件。例如,一个简单的开关状态机:

xml 复制代码
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="off">
    <state id="off">
        <transition event="switch" target="on"/>
    </state>
    <state id="on">
        <transition event="switch" target="off"/>
    </state>
</scxml>

3.2 (可选但推荐) 使用 qscxmlc 编译 SCXML 文件

  • 命令行

    bash 复制代码
    qscxmlc -o LightSwitchMachine.h LightSwitchMachine.scxml
  • CMake

    cmake 复制代码
    find_package(Qt6 COMPONENTS SCXML REQUIRED)
    qt_add_scxml_file(LightSwitchMachine "LightSwitchMachine.scxml" OUTPUT_HEADER LightSwitchMachine.h OUTPUT_SOURCE LightSwitchMachine.cpp)
  • qmake

    qmake 复制代码
    scxml_files = LightSwitchMachine.scxml
    qscxmlc.commands = qscxmlc -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
    QMAKE_EXTRA_COMPILERS += scxmlc

3.3 在 Qt 项目中集成

  1. 配置项目 :确保项目文件(.pro, CMakeLists.txt)包含 scxml 模块。

    • qmake: QT += scxml
    • CMake: find_package(Qt6 COMPONENTS SCXML REQUIRED)target_link_libraries(myapp Qt6::SCXML)
  2. 包含头文件 :如果使用了 qscxmlc,包含生成的头文件 #include "LightSwitchMachine.h";否则使用 #include <QtScxml/QScxmlStateMachine>

  3. 创建状态机实例

    • 未编译

      cpp 复制代码
      QScxmlStateMachine *machine = QScxmlStateMachine::fromFile(":/LightSwitchMachine.scxml");
    • 已编译

      cpp 复制代码
      LightSwitchMachine *machine = new LightSwitchMachine();
  4. 启动状态机

    cpp 复制代码
    machine->start();
  5. 与状态机交互

    • 发送事件

      cpp 复制代码
      // 未编译 (通用方法)
      machine->submitEvent("switch");
      // 已编译 (类型安全方法)
      machine->submitSwitch(); // 假设事件名为 'switch'
    • 查询状态

      cpp 复制代码
      QString currentState = machine->activeStateNames().first(); // 获取根状态下的活动状态名
      // 已编译 (使用枚举)
      if (machine->isActive(LightSwitchMachine::On)) { ... }
    • 连接信号

      cpp 复制代码
      // 状态进入/退出信号
      connect(machine, &QScxmlStateMachine::reachedStableState, this, &MyClass::onStableState);
      connect(machine, &QScxmlStateMachine::stateEntered, this, &MyClass::onStateEntered);
      connect(machine, &QScxmlStateMachine::stateExited, this, &MyClass::onStateExited);
      // 已编译状态机可能有更具体的信号

1、关键特性与优势

  • 可视化与形式化:SCXML 文件可以可视化编辑,状态机行为清晰定义。
  • 复用性:状态机定义(SCXML 文件)独立于业务逻辑代码。
  • 可维护性:复杂状态逻辑集中管理,易于修改。
  • 性能:编译后的状态机运行高效。
  • 集成:与 Qt 的信号/槽、事件循环完美结合。
  • 复杂状态支持:支持嵌套状态、并行状态、历史状态等。

5、示例:编译后状态机的使用 (C++)

cpp 复制代码
#include "LightSwitchMachine.h" // 由 qscxmlc 生成
#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    LightSwitchMachine machine;
    machine.start(); // 启动状态机,初始状态为 "off"

    // 连接信号查看状态变化
    QObject::connect(&machine, &LightSwitchMachine::onEntered, [](const QString &state) {
        qDebug() << "Entered state:" << state;
    });

    // 发送事件切换状态
    machine.submitSwitch(); // 从 off -> on
    machine.submitSwitch(); // 从 on -> off

    return app.exec();
}

6、总结

Qt 的 SCXML 模块为在 Qt 应用程序中实现基于标准的、复杂的、可维护的状态机行为提供了强大的支持。通过编写 SCXML 文件定义状态逻辑,利用 QScxmlStateMachine 运行,并可选地使用 qscxmlc 编译器提升性能和类型安全,开发者能够高效地管理应用的状态流转。

相关推荐
尘中远11 小时前
【Qwt 7.0 系列】坐标轴与刻度系统 —— 刻度引擎、网格、图例与刻度朝内
qt·数据可视化·qcustomplot·qwt·工业软件·科学绘图
sycmancia13 小时前
Qt——多线程间的互斥
开发语言·qt
尘中远18 小时前
【Qwt 7.0 系列】常用图表类型实战 —— 柱状图、散点图、箱线图与直方图
qt·qwt·工业软件·科学绘图
尘中远19 小时前
【Qwt 7.0 系列】交互功能详解 —— 平移、缩放、坐标轴交互与数据拾取
qt·数据可视化·绘图·qcustomplot·qwt·科学绘图
sycmancia19 小时前
Qt——进程与线程的概念
qt
郝学胜-神的一滴20 小时前
Qt 高级编程 034:深耕QWidget底层内核—彻底吃透无边框窗口设计核心原理
开发语言·c++·qt·程序人生·软件开发·用户界面
尘中远20 小时前
【Qwt 7.0 系列】3D 数据可视化 —— OpenGL 高性能三维绘图
qt·3d·qcustomplot·qwt·科学绘图·高性能绘图
满天星830357720 小时前
【Qt】控件(二) (geometry及与frameGeometry的区别)
开发语言·qt
大气的小蜜蜂20 小时前
基于Python+PyQt5+SQLite的药房管理系统实现:事务一致性与界面解耦全流程解析
python·qt·sqlite
尘中远21 小时前
【Qwt 7.0 系列】总体架构解析 —— 从单体到三库模块化的演进
qt·matplotlib·绘图·qwt·科学绘图