当前位置: 首页 > article >正文

Qt 状态机使用说明

一、前言
1、 状态机,有限状态机,Finite State Machine,简写FSM。

2、 状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。

3、 简单说,状态机就是负责执行各种状态的切换。

4、 Qt状态机通过Qt自身事件系统来驱动。

5、 Qt状态机框架和Qt元对象系统紧密结合,各个状态之间的转换通过信号触发,状态可设置QObject子类对象的属性以及调用其方法。

6、 Qt状态机框架中的状态图是分层的,状态可以嵌套在其它状态中,状态机的当前配置由当前活动的状态集组成,状态机有效配置中的所有状态都有一个共同的祖先。

7、 Qt状态机使用场景,主要针对比较复杂的界面,或者需要切换不同状态的控件(如三态按钮),每个状态对应不同的样式,如果自己做状态管理就比较麻烦。

二、所有与Qt状态机有关的类:(带V的常用)
1、 QAbstractState 状态机的基类

2、 QAbstractTransition 在QAbstractState对象之间进行转换的基类

3、 QEventTransition QObject特定于Qt事件的转换

4、 QKeyEventTransition 基于按键事件的转换

5、 QMouseEventTransition 基于鼠标事件的转换

6、 QSignalTransition 基于Qt信号的转换

7、 QStateMachine 层次有限状态机 (V)

8、 QState 状态机的通用状态 (V)

9、 QFinalState 最终状态 (V)

10、 QHistoryState 返回到先前活动的子状态的方法

11、 QStateMachine::SignalEvent 表示一个信号事件

12、 QStateMachine::WrappedEvent 继承QEvent并保存与QObject关联的事件的一个克隆

三、QState
1、 QSignalTransition * addTransition(const typename QtPrivate::FunctionPointer::Object * obj, Func signal, QAbstractState * target)。
(1)、obj: 对象
signal: 信号
target: 目标状态
(2)、添加一个基于Qt信号的转换。
(3)、当对象obj发出信号signal时,该状态就转换到目标状态target。

2、 void assignProperty(QObject * object, const char * name, const QVariant & value);
(1)、object: 对象
name: 对象类中的属性名
value: 给属性要设置的值
(2)、给对象object设置该状态,对象object处于该状态时,属性name的值为value。

3、 void setInitialState(QAbstractState * state)。
(1)、state: 状态
(2)、设置初始状态。
(3)、QState可以设置子状态,子状态隐式地继承父状态的转换,也可以覆盖掉继承父状态的转换。
(4)、当父状态是转换的目标时,状态机应该进入父状态的哪个子状态。

4、 信号void entered()。
(1)、进入状态时,该状态会发出entered()信号。

5、 信号void exited()。
(2)、退出状态时,该状态会发出exited()信号。

6、 信号void activeChanged(bool active)。
(3)、该状态激活/不激活变化时,都会发出activeChanged(bool)信号。

四、QStateMachine
1、 QStateMachine继承于QState。

2、 void addState(QAbstractState * state)。
(1)、state: 状态
(2)、该状态机添加一个状态。

3、 void setInitialState(QAbstractState * state)。
(1)、state: 状态
(2)、设置初始状态。

4、 void start()。
(1)、开启状态机。

5、 信号void finished()。
(1)状态机进入QFinalState时,会发出finished()信号并停止。

6、 状态机是异步执行,是应用程序事件循环的一部分。

五、QFinalState
1、 若状态机未设置顶级最终状态QFinalState,则永远不会结束,关闭程序时,也会崩溃。

2、 若状态机设置了顶级最终状态QFinalState,则当进入顶级最终状态时,状态机会发出QStateMachine::finished()信号,并停止。

六、示例

//QtStateMachineSample.h
#pragma once

#include <QtWidgets/QWidget>
#include <QStateMachine>

QT_BEGIN_NAMESPACE
namespace Ui { class QtStateMachineSample; };
QT_END_NAMESPACE

class QtStateMachineSample : public QWidget
{
    Q_OBJECT

public:
    QtStateMachineSample(QWidget * parent = nullptr);
    ~QtStateMachineSample();

private:
    Ui::QtStateMachineSample * ui = nullptr;

	QStateMachine * m_machine = nullptr;
};


//QtStateMachineSample.cpp
#include "QtStateMachineSample.h"
#include "ui_QtStateMachineSample.h"
#include <QFinalState>

QtStateMachineSample::QtStateMachineSample(QWidget * parent) : QWidget(parent)
{
	ui = new Ui::QtStateMachineSample();
    ui->setupUi(this);

	m_machine = new QStateMachine();

	QState * s1 = new QState();
	QFinalState * finalState = new QFinalState();

	//在构造中写s1,等同于s1->addState(s11)
	QState * s11 = new QState(s1);
	QState * s12 = new QState(s1);
	QState * s13 = new QState(s1);

	s11->assignProperty(ui->labelTestState, "text", "In State S1");
	s12->assignProperty(ui->labelTestState, "text", "In State S2");
	s13->assignProperty(ui->labelTestState, "text", "In State S3");

	s11->addTransition(ui->toolButtonClick, &QToolButton::clicked, s12);
	s12->addTransition(ui->toolButtonClick, &QToolButton::clicked, s13);
	s13->addTransition(ui->toolButtonClick, &QToolButton::clicked, s11);

	QObject::connect(s13, &QState::entered, ui->toolButtonClick, &QToolButton::showMaximized);
	QObject::connect(s13, &QState::exited, ui->toolButtonClick, &QToolButton::showMinimized);

	//当状态机进入s1时,会进入s11状态。
	s1->setInitialState(s11);
	//当用户点击退出按钮,状态机此时不管在s1的哪个子状态下,都会进入finalState状态。
	s1->addTransition(ui->toolButtonQuit, &QToolButton::clicked, finalState);

	m_machine->addState(s1);
	m_machine->addState(finalState);
	m_machine->setInitialState(s1);

	//一旦状态机进入finalState状态,就会发出finished()信号,应用程序退出。
	QObject::connect(m_machine, &QStateMachine::finished, QApplication::instance(), &QCoreApplication::quit);

	//子状态覆盖掉继承父状态的转换
	//当状态机处于s12状态时,点击退出按钮,状态机会忽略s1到finalState的转换,仍然处于s12状态,不退出。
	s12->addTransition(ui->toolButtonQuit, &QToolButton::clicked, s12);

	m_machine->start();
}

QtStateMachineSample::~QtStateMachineSample()
{
	if (m_machine)
	{
		delete m_machine;
		m_machine = nullptr;
	}

    delete ui;
}

http://www.kler.cn/a/466791.html

相关文章:

  • 后台管理系统动态面包屑Breadcrumb组件的实现
  • 【shell编程】报错信息:Non-zero Exit Status(包含7种解决方法)
  • 【LeetCode Hot100 二分查找】搜索插入位置、搜索二维矩阵、搜索旋转排序数组、寻找两个正序数组的中位数
  • 力扣66 加一
  • 【MySQL】九、表的内外连接
  • Hadoop集群之间实现免密登录
  • MT8788安卓核心板_MTK8788核心板参数_联发科模块定制开发
  • HTML——64. 数字输入框和活动条
  • 单片机通信
  • 交换机关于环路、接口绑定、链路聚合的相关知识
  • 游戏引擎学习第72天
  • [paddle] 非线性拟合问题的训练
  • React 性能优化
  • 数仓建模(二) 从关系型数据库到数据仓库的演变
  • 淘宝商品详情API返回值说明:Python爬虫代码示例
  • perf:对hutool的BeanUtil工具类做补充
  • 【51单片机零基础-chapter3:按键:独立按键|||附带常见C语句.逻辑运算符】
  • 中国科技产业化促进会深入深圳企业调研
  • gesp(C++一级)(17)洛谷:B4062:[GESP202412 一级] 温度转换
  • 在Linux系统中使用字符图案和VNC运行Qt Widgets程序
  • IDEA Plugins中搜索不到插件解决办法
  • 自动化测试常考的面试题+答案汇总(持续更新)
  • React 网络请求优化
  • CVSS漏洞评分系统曝出严重缺陷
  • 【源码+文档+调试讲解】“健康早知道”微信小程序
  • 生成对抗网络 (Generative Adversarial Network, GAN) 算法MNIST图像生成任务及CelebA图像超分辨率任务