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

QT 界面编程中使用协程

QT 界面编程中使用协程

  • 一、概述
  • 二、集成
    • 2.1、编译 Acl
    • 2.2、将 Acl 库集成到 QT 项目中
    • 2.3、开始编写代码
      • 2.3.1、QT 程序初始化时初始化 Acl 协程
      • 2.3.2、在界面中创建协程
      • 2.3.3、界面程序退出前需要停止协程调度
      • 2.3.4、在界面线程中下载数据
      • 2.3.5、在协程中延迟创建窗口
    • 2.4、效果展示
    • 2.5、小结

一、概述

人们在谈论协程编程时,往往与编写命令行网络程序有关,如编写网络客户端与网络服务器程序,很少涉及到客户端 UI 相关的界面编程。Acl 协程库是支持在 Windows 下的 UI 界面编程的,因为 Acl 协程的事件引擎支持了界面消息传递过程。最近学习了一下 QT UI 编程,轻松将 Acl 协程与 QT UI 集成在一起,从而实现了 QT 界面协程化,使开发人员在使用 QT 编写界面程序时,编写网络模块变得非常简单。

本文结合 Acl 中 lib_fiber/samples-gui/QtFiber 示例,演示了如何将 Acl 协程功能集成到 QT 界面中,实现了网络模块与界面模块的融合。

二、集成

2.1、编译 Acl

目前 QT IDE 还无法直接使用 Acl 里的 CMakeLists.txt 文件编译 ACL,可以借助于 VC2019 打开 Acl 里的 acl_cpp_vc2019.sln 工程编译 Acl 五个库的动态库,分别为:lib_acl.dll, lib_protocol.dll, lib_acl_cpp.dll, libfiber.dll, libfiber_cpp.dll 及静态导出库:lib_acl.lib, lib_protocol.lib lib_acl_cpp.lib, libfiber.lib, libfiber_cpp.lib。

2.2、将 Acl 库集成到 QT 项目中

参考 lib_fiber/samples-gui/QtFiber/CMakeLists.txt 文件,将 Acl 库的头文件包含进去,如下:

set(acl_path ../../..)include_directories(${acl_path}/lib_acl/include${acl_path}/lib_acl_cpp/include${acl_path}/lib_fiber/c/include${acl_path}/lib_fiber/cpp/include
)

然后设定编译条件:

add_definitions("-DACL_DLL""-DACL_CPP_DLL""-DHTTP_DLL""-DICMP_DLL""-DSMTP_DLL""-DFIBER_CPP_DLL""-D_CRT_SECURE_NO_WARNINGS""-D_WINSOCK_DEPRECATED_NO_WARNINGS"
)

添加库到工程中,如下:

if (CMAKE_BUILD_TYPE STREQUAL "RELEASE")set(acl_libs_path ${CMAKE_CURRENT_SOURCE_DIR}/../../../x64/ReleaseDll)
else()set(acl_libs_path ${CMAKE_CURRENT_SOURCE_DIR}/../../../x64/DebugDll)
endif()set(lib_all ${acl_libs_path}/libfiber_cpp.lib${acl_libs_path}/lib_acl_cpp.lib${acl_libs_path}/lib_protocol.lib${acl_libs_path}/lib_acl.lib${acl_libs_path}/libfiber.lib)target_link_libraries(QtFiber PRIVATE Qt5::Widgets ${lib_all} Ws2_32)add_custom_command(TARGET ${PROJECT_NAME} POST_BUILDCOMMAND ${CMAKE_COMMAND} -E copy_if_different"${acl_libs_path}/libfiber_cpp.dll""${acl_libs_path}/libfiber.dll""${acl_libs_path}/lib_acl_cpp.dll""${acl_libs_path}/lib_acl.dll""${acl_libs_path}/lib_protocol.dll"$<TARGET_FILE_DIR:${PROJECT_NAME}>
)

2.3、开始编写代码

经过摸索研究,想要集成 Acl 协程到 QT UI 程序中,需要采用以下方法(主要是协程的初始化及退出):

2.3.1、QT 程序初始化时初始化 Acl 协程

在调用 QT APP exec() 前,需要先调用 Acl 协程初始化过程,如下:

static void startupCallback() {acl::fiber::schedule_gui(); // Won't return until schedule finished.
}void main() {QApplication app(argc, argv);MainWindow w;w.show();QTimer::singleShot(0, startupCallback);app.exec();
}

可以看出,在调用 app.exec() 前注入了启动函数 startupCallback(),在里面启动了 acl 在界面模式下的协程调度过程 acl::fiber::schedule_gui(),该方法将进入界面消息循环过程,直到协程调度停止后才会返回。

2.3.2、在界面中创建协程

一旦协程调度器启动,就可以创建并运行协程了,可以在主界面上添加一个按钮,当点击该按钮后的处理函数中便可以创建并启动一个协程。比如在例子中,点击 “Start fiber server” 按钮,在处理函数 MainWindow::onStartServer() 中,可以创建一个网络监听服务器,如下:

void MainWindow::onStartServer() {...server_ = new fiber_server("127.0.0.1", 9001, this);server_->start();...
}

这样在界面里就创建了一个 TCP 监听协程,当有连接连接监听地址时,在监听协程里便可以创建一个客户端连接处理协程进行处理,如下:

    while (true) {SOCKET conn = socket_accept(sock);if (conn == INVALID_SOCKET) {break;}acl::fiber* fb = new fiber_echo(conn);fb->start();}

上面例子的客户端协程启动后,便可以进行网络 IO 读写,如下:

    char buf[8192];while (true) {int ret = acl_fiber_recv(conn_, buf, sizeof(buf) - 1, 0);if (ret == -1) {break;}buf[ret] = 0;if (acl_fiber_send(conn_, buf, ret, 0) != ret) {break;}}

2.3.3、界面程序退出前需要停止协程调度

必须保证在界面程序退出前停止协程调度器,否则界面程序无法正常退出,该步骤也非常重要。可以在主界面处理类里重载基类的 void closeEvent(QCloseEvent *event); 方法,在该方法里停止协程调度器,如下:

void MainWindow::closeEvent(QCloseEvent *event) {acl::fiber::schedule_stop(); // 停止协程调度器event->accept();             // 接受关闭事件
}

2.3.4、在界面线程中下载数据

点击主界面中点击HTTP下载按钮,在事件处理函数中创建协程从后端HTTP服务器下载数据,过程如下:

void MainWindow::onUrlGet() {...go[this] {const char *url = "http://www.baidu.com/";acl::http_request req(url);if (!req.request(nullptr, 0)) {printf("Send HTTP request failed\r\n");return;}acl::string body;if (!req.get_body(body)) {printf("Get HTTP body error\r\n");return;}qDebug() << "Got body:" << body.c_str();...};
}

2.3.5、在协程中延迟创建窗口

如果想某个窗口延迟创建,不必借助定时器,直接在协程中就可以轻松实现:

void MainWindow::delayCreate() {go[this] {acl::fiber::delay(5000); // 休眠 5 秒InputDialog dialog(this);dialog.exec();};qDebug() << "Fiber was created to create one window after a while";
}

2.4、效果展示

编译运行 acl/lib_fiber/samples-gui/QtFiber/ 工程,可以得到以下运行界面:
fiber-qt-ui 在前面窗口中,右边请求HTTP服务器时的HTTP请求头,右连接为后端服务器返回的HTTP响应头,该下载过程中在协程中进行,运行结果显示在主界面上;

  • 窗口下方的进度条为客户端协程与服务端协程交互时的交互进度展示。

2.5、小结

以上便是如何编译集成 Acl 协程到 QT 界面程序的方法,主要的要点是:

  • 需要使用 vc2019 编译 Acl 的动态库,并集成至 QT 界面程序的工程文件中;
  • 编程时需要注意:
    • 在启动 QT (即调用 app.exec())前,需要先启动 Acl 协程调度器;
    • 在主界面类里需要重载基类关闭虚方法 closeEvent(),并在该方法里停止 Acl 协程调度器;
    • 因为协程运行在界面的线程空间中,所以可以在协程中直接操作界面上的窗口对象,避免了线程之间的消息传递过程。

注: Acl库下载:https://github.com/acl-dev/acl/

相关文章:

QT 界面编程中使用协程

QT 界面编程中使用协程 一、概述二、集成2.1、编译 Acl2.2、将 Acl 库集成到 QT 项目中2.3、开始编写代码2.3.1、QT 程序初始化时初始化 Acl 协程2.3.2、在界面中创建协程2.3.3、界面程序退出前需要停止协程调度2.3.4、在界面线程中下载数据2.3.5、在协程中延迟创建窗口 2.4、效…...

macOS 开发环境配置与应用开发

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

第13讲 实践:设计SLAM系统

设计一个视觉里程计&#xff0c;理解SLAM软件框架如何搭建&#xff0c;理解视觉里程计设计容易出现的问题以及解决方法。 目录 1、工程目标 2、工程框架 3、实现 附录 1、工程目标 实现一个精简版的双目视觉里程计。由一个光流追踪的前端和一个局部BA的后端组成。 2、工程…...

NeRF2: Neural Radio-Frequency Radiance Fields 笔记

任务&#xff1a;用 NeRF 对无线信号的传播进行建模&#xff0c;建模完成后可以用NeRF网络生成新位置下的信号。生成的信号用于指纹定位、信道估计等下游任务。 核心思路 在视觉 NeRF 的基础上&#xff0c;根据无线信号的特点修改了隐式场模型、渲染函数&#xff0c;网络的输…...

以太网交换安全:MAC地址表安全

一、MAC地址表安全 MAC地址表安全是网络安全中的一个重要方面&#xff0c;它涉及到网络设备的MAC地址表的管理和保护。以下是对MAC地址表安全的详细介绍&#xff1a; &#xff08;1&#xff09;基本概念 定义&#xff1a;MAC地址表是网络设备&#xff08;如交换机&#xff0…...

CSS综合页布面局案例

写的比较一般,如果想要参考可以点击链接。 CSS综合案例(登录页面)资源-CSDN文库 引言: 我们学习CSS和HTML都是为了想要做一个网页布局,但是每逢上手可能就会需要查阅很多语言,我觉得是没有什么问题的,熟能生巧,编程是需要练的,但是写网页的时候需要实现某个效果时需…...

低代码可视化-UniApp二维码可视化-代码生成器

市面上提供了各种各样的二维码组件&#xff0c;做了一简单的uniapp二维码组件&#xff0c;二维码实现依赖davidshimjs/qrcodejs。 组件特点 跨浏览器支持&#xff1a;利用Canvas元素实现二维码的跨浏览器兼容性&#xff0c;兼容微信小程序、h5、app。 无依赖性&#xff1a;QR…...

Electron 使用 Nodemon 配置自动重启

在Electron项目中&#xff0c;每次修改了代码都需要手动关闭应用&#xff0c;再执行npm start重启应用。 Nodemon 是一个非常实用的工具&#xff0c;主要用于在开发 Node.js 应用时自动监测文件的变化并重新启动服务器。 安装nodemon 开发环境安装nodemon&#xff1a; npm …...

JVM和GC监控技术

一、监控技术简介 JVM是什么&#xff1f;项目里面有JVM吗&#xff1f;JVM跟Tomcat有什么关系&#xff1f;为什么需要去分析JVM&#xff1f; 1. JVM(全称&#xff1a;Java Virtual Machine)&#xff0c;Java虚拟机 是Java程序运行的环境&#xff0c;它是一个虚构的计算机&…...

Android中级控件

文章目录 图形定制1.图形Drawable2.形状图像3.九宫格图片4.状态列表图形 选择按钮1.复选框CheckBox2.开关按钮Switch3.单选按钮 文本输入1.编辑框EditText2.焦点变更监听器3.文本变化监听器 对话框1.提醒对话框2.日期对话框DatePickerDialog3.时间对话框TimePickerDialog 图形定…...

WebSocket消息防丢ACK和心跳机制对信息安全性的作用及实现方法

WebSocket消息防丢ACK和心跳机制对信息安全性的作用及实现方法 在现代即时通讯&#xff08;IM&#xff09;系统和实时通信应用中&#xff0c;WebSocket作为一种高效的双向通信协议&#xff0c;得到了广泛应用。然而&#xff0c;在实际使用中&#xff0c;如何确保消息的可靠传输…...

生信初学者教程(二十二):Boruta+RF筛选候选标记物

文章目录 介绍加载R包导入数据准备数据机器学习特征筛选数据分割基础模型Boruta特征筛选调参最终分类模型测试集验证标记基因输出结果总结介绍 采用了Boruta结合 RF(Random Forest) 的方法,对差异基因(参考 @sec-different-limma) 进行了特征筛选。通过这种方法,能够从大…...

JVM Class类文件结构

国庆节快乐 2024年10月2日17:49:22 目录 前言 magic 数 文件版本 使用JClassLib观察class文件 一般信息 接口 常量池 字段 方法 常量池计数器 常量池 类型 CONSTANT_Methodref_info CONSTANT_Class_info 类型结构总表 访问标志 类索引, …...

解决 GitHub 文件大小限制的问题

要解决 GitHub 文件大小限制的问题&#xff0c;可以使用 Git Large File Storage (Git LFS)。以下是设置步骤&#xff1a; 安装 Git LFS&#xff1a; 对于 macOS&#xff1a;brew install git-lfs对于 Windows&#xff1a;从 Git LFS官网 下载并安装。 初始化 Git LFS&#xff…...

wordpress源码资源站整站打包32GB数据,含6.7W条资源数据

源码太大了&#xff0c;足足32gb&#xff0c;先分享给大家。新手建立资源站&#xff0c;直接用这个代码部署一下&#xff0c;数据就够用了。辅助简单做下seo&#xff0c;一个新站就OK了。 温馨提示&#xff1a;必须按照顺序安装 代码下载...

金融领域的人工智能——Palmyra-Fin 如何重新定义市场分析

引言 DigiOps与人工智能 正在改变全球各行各业&#xff0c;并带来新的创新和效率水平。人工智能已成为金融领域的强大工具&#xff0c;为市场分析、风险管理和决策带来了新方法。金融市场以复杂性和快速变化而闻名&#xff0c;人工智能处理大量数据并提供清晰、可操作的见解的…...

STL--string类

我们从这篇文章之后就正式开始学习STL的string&#xff0c;字面看起来是不是像C语言里面的字符串之类的处理方法&#xff0c;是的&#xff0c;C里面也是对字符串的一些处理函数&#xff0c;但是C有很多这样的函数&#xff0c;给大家推荐一个网站 &#xff0c;这个网站是C的官网…...

iptables 的NDAT报错bash: 9000: command not forward

外网主机设置&#xff1a; iptables -t nat -A PREROUTING -d 192.168.3.51 -p tcp --dport 9000 -j DNAT --to-destination 192.168.3.61:22 本地shell连接&#xff1a; PS C:> ssh root192.168.3.51 9000 显示如下操作&#xff1a; PS C:> ssh root192.168.3.51 9000…...

快速了解:MySQL InnoDB和MyISAM的区别

目录 一、序言二、InnoDB和MyISAM对比1、InnoDB特性支持如下2、MyISAM特性支持如下 三、两者核心区别1、事务支持2、锁机制3、索引结构4、缓存机制5、故障恢复6、使用场景 一、序言 在MySQL 8.0中&#xff0c;InnoDB是默认的存储引擎。除了InnoDB&#xff0c;MySQL还支持其它的…...

TI DSP TMS320F280025 Note14:模数转换器ADC原理分析与应用

TMS320F280025 模数转换器ADC原理分析与应用 ` 文章目录 TMS320F280025 模数转换器ADC原理分析与应用逐次比较型ADC和双积分型ADC工作原理逐次比较型 ADC双积分型 ADC280025ADCADC原理分析ADC时钟SOCSOC内部原理ADC触发方式ADC采集(采样和保持)窗口通道寄生电容基准电压发生器模…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...