Qt之QStateMachine等待
在项目中经常需要等待,我们模拟0-30的数,假如我们其中5, 25的数需要进行等待,等待用户处理完自己事情后,按下按钮继续,找Qt的项目中有一个
QStateMachine
qstatemmachine类提供了一个分层有限状态机。
QStateMachine基于Statecharts的概念和符号。qstatemmachine是状态机框架的一部分。
状态机管理一组状态(从QAbstractState继承的类)和这些状态之间的转换(QAbstractTransition的后代);这些状态和转换定义了一个状态图。一旦构建了状态图,状态机就可以执行它。qstatemmachine的执行算法基于状态图XML (SCXML)算法。该框架的概述给出了几个状态图和构建它们的代码。
使用addState()函数向状态机添加顶级状态。使用removeState()函数删除状态。不鼓励在机器运行时删除状态。
在机器启动之前,必须设置初始状态。初始状态是机器启动时进入的状态。然后可以启动状态机。当进入初始状态时,就会发出started()信号。
机器是事件驱动的,并保持自己的事件循环。事件通过postEvent()发送到机器。请注意,这意味着它是异步执行的,并且如果没有正在运行的事件循环,它将无法进行。你通常不需要将事件直接发布到机器上,因为Qt的转换,例如,QEventTransition和它的子类,会处理这个。但是对于由事件触发的自定义转换,postEvent()很有用。
状态机处理事件并进行转换,直到进入顶级最终状态;然后状态机发出finished()信号。您还可以显式地stop()状态机。在这种情况下,会发出stopped()信号。
下面的代码片段显示了一个状态机,当按钮被点击时,状态机将完成:
QPushButton button;QStateMachine machine;QState *s1 = new QState();s1->assignProperty(&button, "text", "Click me");QFinalState *s2 = new QFinalState();s1->addTransition(&button, SIGNAL(clicked()), s2);machine.addState(s1);machine.addState(s2);machine.setInitialState(s1);machine.start();
那么我们实现自己
Processor类
#ifndef PROCESSOR_H
#define PROCESSOR_H#include <QObject>
#include <QStateMachine>
#include <QState>
#include <QFinalState>class Processor : public QObject
{Q_OBJECT
public:explicit Processor(QObject *parent = nullptr);void startProcessing();void resumeProcessing();signals:void progressUpdated(int value);void runSig();void paused();void finished();private:void processNextItem();bool isRunning() const;private:QStateMachine *m_machine;QState *m_runningState;QState *m_pausedState;QFinalState *m_finishedState;int m_currentIndex;
};#endif // PROCESSOR_H
#include "processor.h"
#include <QDebug>
#include <QTimer>
#include <QThread>Processor::Processor(QObject *parent): QObject(parent),m_machine(new QStateMachine(this)),m_runningState(new QState(m_machine)),m_pausedState(new QState(m_machine)),m_finishedState(new QFinalState(m_machine)),m_currentIndex(0)
{// 配置运行状态connect(m_runningState, &QState::entered, [this]() {qDebug() << "Entered running state";processNextItem();});// 配置暂停状态connect(m_pausedState, &QState::entered, [this]() {qDebug() << "Entered paused state";});// 配置暂停状态
// connect(m_finishedState, &QState::entered, [this]() {
// qDebug() << "Entered finished state";
// });// 配置状态转换m_runningState->addTransition(this, &Processor::paused, m_pausedState);m_pausedState->addTransition(this, &Processor::runSig, m_runningState);m_runningState->addTransition(this, &Processor::finished, m_finishedState);// 配置状态机m_machine->setInitialState(m_runningState);}bool Processor::isRunning() const
{return m_machine->isRunning();
}void Processor::startProcessing()
{if (!m_machine->isRunning()) {qDebug() << "Starting processing...";m_machine->start();}
}void Processor::resumeProcessing()
{++m_currentIndex;emit runSig();}void Processor::processNextItem()
{if (m_currentIndex >= 30) {emit finished();return;}emit progressUpdated(m_currentIndex);if (m_currentIndex == 5 || m_currentIndex == 25) {qDebug() << "--- Reached pause point ---";emit paused();}else { // 只有非暂停点时继续自动处理m_currentIndex++;QThread::msleep(200); //模拟耗时操作processNextItem();}
}
单例模式
#ifndef TASKPROCESSOR_H
#define TASKPROCESSOR_H#include <QObject>
#include <QStateMachine>
#include <QState>
#include <QFinalState>
#include <QQueue>
#include <QMutex>
#include <functional>class TaskProcessor : public QObject
{Q_OBJECT
public:// 单例接口,保证全局唯一static TaskProcessor& getInstance() {static TaskProcessor processor;return processor;}// 添加任务到队列void addTask(const std::function<void()>& task);// 开始处理任务队列void startProcessing();// 暂停任务处理(例如等待外部事件)void pauseProcessing();// 恢复任务处理void resumeProcessing();signals:// 任务状态信号,可根据需求扩展void pausedSig();void resumeSig();void taskStarted();void taskFinished();void allTasksFinished();private:// 构造函数私有,确保单例explicit TaskProcessor(QObject *parent = nullptr);Q_DISABLE_COPY(TaskProcessor)// 内部处理任务队列的方法void processNextTask();// 任务队列及同步保护QQueue<std::function<void()>> m_taskQueue;QMutex m_mutex;// 状态机及状态QStateMachine *m_machine;QState *m_runningState;QState *m_pausedState;QFinalState *m_finishedState;
};#endif // TASKPROCESSOR_H
#include "processor.h"
#include <QDebug>
#include <QThread>TaskProcessor::TaskProcessor(QObject *parent): QObject(parent),m_machine(new QStateMachine(this)),m_runningState(new QState(m_machine)),m_pausedState(new QState(m_machine)),m_finishedState(new QFinalState(m_machine))
{// 配置运行状态:进入运行状态时,尝试处理下一个任务connect(m_runningState, &QState::entered, this, [this]() {qDebug() << "Entered running state";processNextTask();});// 配置暂停状态:仅做记录,具体暂停逻辑可通过状态机外部控制connect(m_pausedState, &QState::entered, this, [this]() {qDebug() << "Entered paused state";});// 状态切换配置:暂停和恢复m_runningState->addTransition(this, SIGNAL(pausedSig()), m_pausedState);m_pausedState->addTransition(this, SIGNAL(resumeSig()), m_runningState);// 当任务全部处理完毕时,切换到结束状态m_runningState->addTransition(this, SIGNAL(allTasksFinished()), m_finishedState);// 状态机初始状态设为运行状态m_machine->setInitialState(m_runningState);
}void TaskProcessor::addTask(const std::function<void()>& task)
{QMutexLocker locker(&m_mutex);m_taskQueue.enqueue(task);
}void TaskProcessor::startProcessing()
{if (!m_machine->isRunning()) {qDebug() << "Starting Task Processing...";m_machine->start();}
}void TaskProcessor::pauseProcessing()
{// 可以发出信号通知状态机进入暂停状态qDebug() << "Requesting pause...";emit pausedSig(); // 此处 SIGNAL 与状态机转换绑定
}void TaskProcessor::resumeProcessing()
{// 发出信号恢复处理qDebug() << "Requesting resume...";emit resumeSig();processNextTask();
}void TaskProcessor::processNextTask()
{QMutexLocker locker(&m_mutex);if (m_taskQueue.isEmpty()) {qDebug() << "All tasks finished.";emit allTasksFinished();return;}// 取出队列中的下一个任务std::function<void()> task = m_taskQueue.dequeue();// 在运行状态下开始任务,发出任务开始信号emit taskStarted();qDebug() << "Processing a task...";// 这里可以在一个独立线程中运行任务,避免阻塞状态机// 例如:QThread::sleep() 或者使用 QtConcurrenttask();// 任务执行完成,发出任务结束信号emit taskFinished();}
相关文章:
Qt之QStateMachine等待
在项目中经常需要等待,我们模拟0-30的数,假如我们其中5, 25的数需要进行等待,等待用户处理完自己事情后,按下按钮继续,找Qt的项目中有一个 QStateMachineqstatemmachine类提供了一个分层有限状态机。 QSta…...
Wireshark 插件开发实战指南
Wireshark 插件开发实战指南 环境搭建流程图 #mermaid-svg-XpNibno7BIyfzNn5 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XpNibno7BIyfzNn5 .error-icon{fill:#552222;}#mermaid-svg-XpNibno7BIyfzNn5 .error-t…...

基于SpringBoot的“青少年心理健康教育网站”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“青少年心理健康教育网站”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 实体属性图 系统首页界…...
23-整数转罗马数字
代码 测试用例 测试结果 测试结果 12. 整数转罗马数字 中等 相关标签 相关企业 七个不同的符号代表罗马数字,其值如下: 符号值I1V5X10L50C100D500M1000 罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以…...

SpringBoot+Redis+Mybatis-plus黑马点评
短信登录 基于Session实现登录 流程: 发送短信验证码-->短信验证码注册登录-->校验登录状态(保存用户到ThreadLocal,方便后续使用) 不能每次请求服务都要进行登录状态校验,解决办法:拦截器 在Sp…...
深入剖析 OpenCV:全面掌握基础操作、图像处理算法与特征匹配
深入剖析 OpenCV:全面掌握基础操作、图像处理算法与特征匹配 一、引言二、OpenCV 的安装(一)使用 pip 安装(二)使用 Anaconda 安装 三、OpenCV 基础操作(一)图像的读取、显示与保存(…...
【C语言显示Linux系统参数】
在C语言中,可以通过调用Linux系统提供的API来获取和显示系统参数。以下是一些常见的系统参数及其获取方法: 1. 获取系统名称和版本 可以使用uname函数来获取系统名称、版本等信息。 #include <stdio.h> #include <sys/utsname.h>int main…...
突破Ajax跨域困境,解锁前端通信新姿势
一、引言 在当今的 Web 开发领域,前后端分离的架构模式已经成为主流,它极大地提升了开发效率和项目的可维护性。在这种开发模式下,前端通过 Ajax 技术与后端进行数据交互,然而,跨域问题却如影随形,成为了开…...
Kotlin协变与逆变区别
在Kotlin中,协变和逆变是泛型编程中的两个重要概念,它们允许我们在类型系统中更加灵活地处理类型关系。 1.协变:协变允许我们使用比原始类型更具体的类型。在kotlin中,通过在类型参数上加out关键字来表示协变,生产者,例…...
driver中为什么要使用非阻塞赋值
1. 模拟硬件时序行为 实际硬件行为:DUT的输入信号通常在时钟边沿被采样。Driver需要确保信号的更新与时钟同步,而非阻塞赋值的延迟更新特性(在时间步结束时统一生效)能够准确模拟寄存器的行为。 示例: always (posedg…...

模板字符串【ES6】
“路漫漫其修远兮,吾将上下而求索。”—— 屈原《离骚》 目录 什么是模板字符串?模板字符串特性及代码举例:详细举例用法: 什么是模板字符串? 模板字符串(Template Literals)是JavaScript中引入…...
通往 AI 之路:Python 机器学习入门-数据结构
Python 数据结构 Python 提供了多种数据结构来存储和操作数据,其中列表(list)、字典(dict)、元组(tuple)和集合(set)是最常用的几种。本章将详细介绍这些数据结构的基本…...
我们应该如何优化UI(基于UGUI)
这是一道面试题,下面,我们来详细分析这个问题。 目录 1. 减少 Draw Call 合理设置图集 避免材质和 Shader 的频繁切换 减少 UI 元素的重叠 2. 优化UI布局 3. 优化UI元素的渲染 4.优化UI动画 5. 优化 UI 事件处理 6. 运行时优化 1. 减少 Draw C…...
CSS3 圆角:实现与优化指南
CSS3 圆角:实现与优化指南 随着网页设计的发展,CSS3 圆角已经成为了现代网页设计中不可或缺的元素之一。本文将详细讲解 CSS3 圆角的基本用法、实现方式以及优化技巧,帮助您在网页设计中更好地运用这一功能。 一、CSS3 圆角基本用法 1.1 基…...
【网络安全 | 扫描子域+发现真实IP】CloakQuest3r安装使用详细教程
原创文章,禁止转载。 本文仅作学习交流使用,不得用于非法渗透,笔者不承担任何责任。 文章目录 简介功能介绍执行流程限制安装步骤可选功能:SecurityTrails API使用示例简介 CloakQuest3r 是一款强大的 Python 工具,专为揭示受 Cloudflare 及类似服务保护的网站真实 IP 地…...

Mellanox OFED驱动如何给全局编译添加gcc的编译选项?(subdir-ccflags-y += -Wall)
背景 有些时候编译驱动需要给全局加一个编译选项,假设configure已经完成。可以直接在Makefile中修改 添加方式 修改OFED驱动目录下的: ./Makefile subdir-ccflags-y -Wall修改效果: 然后执行make,就能让添加的编译选项生效…...

【愚公系列】《Python网络爬虫从入门到精通》037-文件的存取
标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...

【一起学Rust | Tauri2.0框架】单实例应用程序的深入解析:零漏洞实现与优化实战
文章目录 前言一、 单实例应用的意义二、 实现单实例应用的方法1 Windows下的实现1.1 创建命名Mutex1.2 在Tauri应用中集成Mutex检查 2 macOS下的实现2.1 获取Bundle Identifier2.2 检查是否已经有实例在运行 3 Linux下的实现3.1 获取进程列表3.2 检查是否已经有实例在运行 4 在…...
PhyloSuite v1.2.3安装与使用-生信工具049
PhyloSuite 一个好用的win集成建树平台,官方相关文档视频等做的可好了PhyloSuite (jushengwu.com) 官网 https://github.com/dongzhang0725/PhyloSuite/releases #官网 http://phylosuite.jushengwu.com/dongzhang0725.github.io/installation/ #官方说明文档…...
使用Apache Lucene构建高效的全文搜索服务
使用Apache Lucene构建高效的全文搜索服务 在现代应用程序中,全文搜索功能是不可或缺的一部分。无论是电子商务网站、内容管理系统,还是数据分析平台,快速、准确地搜索大量数据是提升用户体验的关键。Apache Lucene 是一个强大的全文搜索引擎…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...