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

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等待

在项目中经常需要等待&#xff0c;我们模拟0-30的数&#xff0c;假如我们其中5&#xff0c; 25的数需要进行等待&#xff0c;等待用户处理完自己事情后&#xff0c;按下按钮继续&#xff0c;找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的“青少年心理健康教育网站”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 实体属性图 系统首页界…...

23-整数转罗马数字

代码 测试用例 测试结果 测试结果 12. 整数转罗马数字 中等 相关标签 相关企业 七个不同的符号代表罗马数字&#xff0c;其值如下&#xff1a; 符号值I1V5X10L50C100D500M1000 罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以…...

SpringBoot+Redis+Mybatis-plus黑马点评

短信登录 基于Session实现登录 流程&#xff1a; 发送短信验证码-->短信验证码注册登录-->校验登录状态&#xff08;保存用户到ThreadLocal&#xff0c;方便后续使用&#xff09; 不能每次请求服务都要进行登录状态校验&#xff0c;解决办法&#xff1a;拦截器 在Sp…...

深入剖析 OpenCV:全面掌握基础操作、图像处理算法与特征匹配

深入剖析 OpenCV&#xff1a;全面掌握基础操作、图像处理算法与特征匹配 一、引言二、OpenCV 的安装&#xff08;一&#xff09;使用 pip 安装&#xff08;二&#xff09;使用 Anaconda 安装 三、OpenCV 基础操作&#xff08;一&#xff09;图像的读取、显示与保存&#xff08;…...

【C语言显示Linux系统参数】

在C语言中&#xff0c;可以通过调用Linux系统提供的API来获取和显示系统参数。以下是一些常见的系统参数及其获取方法&#xff1a; 1. 获取系统名称和版本 可以使用uname函数来获取系统名称、版本等信息。 #include <stdio.h> #include <sys/utsname.h>int main…...

突破Ajax跨域困境,解锁前端通信新姿势

一、引言 在当今的 Web 开发领域&#xff0c;前后端分离的架构模式已经成为主流&#xff0c;它极大地提升了开发效率和项目的可维护性。在这种开发模式下&#xff0c;前端通过 Ajax 技术与后端进行数据交互&#xff0c;然而&#xff0c;跨域问题却如影随形&#xff0c;成为了开…...

Kotlin协变与逆变区别

在Kotlin中&#xff0c;协变和逆变是泛型编程中的两个重要概念&#xff0c;它们允许我们在类型系统中更加灵活地处理类型关系。 1.协变&#xff1a;协变允许我们使用比原始类型更具体的类型。在kotlin中&#xff0c;通过在类型参数上加out关键字来表示协变,生产者&#xff0c;例…...

driver中为什么要使用非阻塞赋值

1. 模拟硬件时序行为 实际硬件行为&#xff1a;DUT的输入信号通常在时钟边沿被采样。Driver需要确保信号的更新与时钟同步&#xff0c;而非阻塞赋值的延迟更新特性&#xff08;在时间步结束时统一生效&#xff09;能够准确模拟寄存器的行为。 示例&#xff1a; always (posedg…...

模板字符串【ES6】

“路漫漫其修远兮&#xff0c;吾将上下而求索。”—— 屈原《离骚》 目录 什么是模板字符串&#xff1f;模板字符串特性及代码举例&#xff1a;详细举例用法&#xff1a; 什么是模板字符串&#xff1f; 模板字符串&#xff08;Template Literals&#xff09;是JavaScript中引入…...

通往 AI 之路:Python 机器学习入门-数据结构

Python 数据结构 Python 提供了多种数据结构来存储和操作数据&#xff0c;其中列表&#xff08;list&#xff09;、字典&#xff08;dict&#xff09;、元组&#xff08;tuple&#xff09;和集合&#xff08;set&#xff09;是最常用的几种。本章将详细介绍这些数据结构的基本…...

我们应该如何优化UI(基于UGUI)

这是一道面试题&#xff0c;下面&#xff0c;我们来详细分析这个问题。 目录 1. 减少 Draw Call 合理设置图集 避免材质和 Shader 的频繁切换 减少 UI 元素的重叠 2. 优化UI布局 3. 优化UI元素的渲染 4.优化UI动画 5. 优化 UI 事件处理 6. 运行时优化 1. 减少 Draw C…...

CSS3 圆角:实现与优化指南

CSS3 圆角&#xff1a;实现与优化指南 随着网页设计的发展&#xff0c;CSS3 圆角已经成为了现代网页设计中不可或缺的元素之一。本文将详细讲解 CSS3 圆角的基本用法、实现方式以及优化技巧&#xff0c;帮助您在网页设计中更好地运用这一功能。 一、CSS3 圆角基本用法 1.1 基…...

【网络安全 | 扫描子域+发现真实IP】CloakQuest3r安装使用详细教程

原创文章,禁止转载。 本文仅作学习交流使用,不得用于非法渗透,笔者不承担任何责任。 文章目录 简介功能介绍执行流程限制安装步骤可选功能:SecurityTrails API使用示例简介 CloakQuest3r 是一款强大的 Python 工具,专为揭示受 Cloudflare 及类似服务保护的网站真实 IP 地…...

Mellanox OFED驱动如何给全局编译添加gcc的编译选项?(subdir-ccflags-y += -Wall)

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

【愚公系列】《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集成建树平台&#xff0c;官方相关文档视频等做的可好了PhyloSuite (jushengwu.com) 官网 https://github.com/dongzhang0725/PhyloSuite/releases #官网 http://phylosuite.jushengwu.com/dongzhang0725.github.io/installation/ #官方说明文档…...

使用Apache Lucene构建高效的全文搜索服务

使用Apache Lucene构建高效的全文搜索服务 在现代应用程序中&#xff0c;全文搜索功能是不可或缺的一部分。无论是电子商务网站、内容管理系统&#xff0c;还是数据分析平台&#xff0c;快速、准确地搜索大量数据是提升用户体验的关键。Apache Lucene 是一个强大的全文搜索引擎…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;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&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;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求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

VisualXML全新升级 | 新增数据库编辑功能

VisualXML是一个功能强大的网络总线设计工具&#xff0c;专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑&#xff08;如DBC、LDF、ARXML、HEX等&#xff09;&#xff0c;并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...