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 是一个强大的全文搜索引擎…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
