Qt自定义事件实现及子线程向主线程传送事件消息

2024-06-11 20:58

本文主要是介绍Qt自定义事件实现及子线程向主线程传送事件消息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

近期在又一次学习Qt的时候,由于要涉及到子线程与主线程传递消息,所以便琢磨了一下。顺便把有用的记录下来,方便自己以后查询及各位同仁的參考!

特此声明,本篇博文主要讲述有用的,也就是直接说明怎么实现,就不打算陈述一大堆理论啦,只是,还是建议大家去查查对应的理论比較好。这样能对Qt的消息传送机制的理解更加深入。

依据网上大多数人的资料,要实现自己定义消息,须要从QEvent 派生一个自己定义的事件;事实上也能够不须要,仅仅要使用QEvent::Type自己定义一个事件即可了。

在这里,本人把两种实现方法都在这里讲述一下!

 

一、这里先讲述使用 QEvent::Type 定义一个自己定义事件

      1、新建一个新的project “myEvent” 。在 ui 界面加入一个button,并未button加入 onclick() 响应函数。

      2、在 widget.h 头文件使用 QEvent::Type 定义两个自己定义事件。

      3、又一次实现 event() 虚函数

<span style="color:#000000">bool event(QEvent* e);</span>

      4、加入 #include<QEvent>

 

整个头文件例如以下:

 

<span style="color:#000000">#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QEvent>namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();bool event(QEvent* e);private slots:void on_pushButton_clicked();private:Ui::Widget *ui;QEvent::Type myEvent1;QEvent::Type myEvent2;};#endif // WIDGET_H</span>

 

      5、使用QEvent::registerEventType() 静态函数为刚才两个自己定义事件注冊值。

      6、又一次实现 event()  函数 。

 

      7、在 button响应函数里面发送时间消息。

widget.cpp 文件例如以下:

 

<span style="color:#000000">#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QCoreApplication>
#include <QDebug>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);myEvent1 = static_cast<QEvent::Type>(QEvent::registerEventType(-1));myEvent2 = static_cast<QEvent::Type>(QEvent::registerEventType(-1));
}Widget::~Widget()
{delete ui;
}bool Widget::event(QEvent* e)
{if(e->type() == myEvent1){QMessageBox::warning(this, tr("event"), tr("myEvent1"), QMessageBox::Yes); return true;}else if(e->type() == myEvent2){QMessageBox::warning(this, tr("event"), tr("myEvent2"), QMessageBox::Yes); return true;}return QWidget::event(e);
}void Widget::on_pushButton_clicked()
{QCoreApplication::sendEvent(this, &QEvent(myEvent1));QCoreApplication::sendEvent(this, &QEvent(myEvent2));}</span>

编译执行后界面例如以下:

 

 

 

二、从 QEvent 派生一个自己定义事件类,类名取为 myEvent 。

 

      1、myevent.h 头文件例如以下。里面自己定义了三个自己定义事件,分别为 m_event1, m_event2, m_event3:

 

<span style="color:#000000">#ifndef MYEVENT_H
#define MYEVENT_H#include <QEvent>class myEvent : public QEvent
{
public:myEvent(Type e);public:static Type m_event1;static Type m_event2;static Type m_event3;
};#endif // MYEVENT_H
</span>

 

 

2 、在myevent.cpp 文件里面使用QEvent::registerEventType() 为自己定义的事件注冊。

myevent.cpp 文件例如以下:

 

<span style="color:#000000">#include "myevent.h"
#include <QEvent>QEvent::Type myEvent::m_event1 = static_cast<QEvent::Type>(QEvent::registerEventType());
QEvent::Type myEvent::m_event2 = static_cast<QEvent::Type>(QEvent::registerEventType());
QEvent::Type myEvent::m_event3 = static_cast<QEvent::Type>(QEvent::registerEventType());myEvent::myEvent(Type e):QEvent(e)
{
}
</span>

 

 

3、在 widget.cpp 文件 加入   myevent.h 头文件 。

4、改动 widget.cpp 文件中面的button响应函数例如以下:

 

<span style="color:#000000">void Widget::on_pushButton_clicked()
{myEvent e(myEvent::m_event1);QCoreApplication::sendEvent(this, &e);
}</span>

5、改动 widget.cpp 文件中面的 event() 函数例如以下:

 

 

<span style="color:#000000">bool Widget::event(QEvent* e)
{if(e->type() == myEvent1){QMessageBox::warning(this, tr("event"), tr("myEvent1"), QMessageBox::Yes); <pre name="code" class="cpp">        return true;}else if(e->type() == myEvent2){QMessageBox::warning(this, tr("event"), tr("myEvent2"), QMessageBox::Yes);
<pre name="code" class="cpp"><pre name="code" class="cpp">        return true;</span>

 

 

 }else if(e->type() == myEvent::m_event1){ QMessageBox::warning(this, tr("myEvent"), tr("m_event1"), QMessageBox::Yes); return true; } else if(e->type() == myEvent::m_event2){ QMessageBox::warning(this, tr("myEvent"), tr("m_event2"), QMessageBox::Yes); return true; } return QWidget::event(e);}

 
 

然后又一次编译执行,效果例如以下:

 

 

三 、 前面讲的都是在主线程里面传递事件消息,接下来讲述怎样 在子线程里面 往主线程 传递事件消息。

      1、从 QThread 派生一个自己定义事件类,类名取为 myThread , 并又一次实现 run() 虚函数。mythread.h 头文件例如以下:

 

<span style="color:#000000">#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QThread>class myThread : public QThread
{Q_OBJECT
public:explicit myThread(QObject *parent = 0);signals:public slots:protected:void run();
};#endif // MYTHREAD_H</span>


      2、在mythread.cpp 里面又一次实现 run() 函数。在里面实现向主线程发送事件消息,mythread.cpp 文件例如以下:

 

 

<span style="color:#000000">#include "mythread.h"
#include "myevent.h"
#include <QCoreApplication>myThread::myThread(QObject *parent) :QThread(parent)
{
}void myThread::run()
{myEvent e(myEvent::m_event2);QCoreApplication::postEvent(this->parent(), new myEvent(myEvent::m_event2));//this->exec();
}
</span>


      3、在 widget.h        里面加入 mythread.h 头文件, 然后定义一个子线程对象, 例如以下:

 

#include"mythread.h"

 

myThread*m_pThread;

 

      4、在堆内存里面为m_pThread开辟一个内存空间,例如以下:

 

<span style="color:#000000"><span style="color:#000000;">Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);m_pThread = new myThread(this);。。</span>

 

。。。。 }</span>


      5、在 ui  界面 加入还有一个button。并为它加入 onclick() 事件响应。然后在里面执行子线程,例如以下:

 

 

<span style="color:#000000">void Widget::on_pushButton_2_clicked()
{m_pThread->start();
}
</span>

编译执行程序,效果例如以下:

 

 

四、QCoreApplication::postEvent(); 和 QCoreApplication::sendEvent();     的差别。

在前面的程序中发送 事件消息 的时候用到了 QCoreApplication::postEvent(); 和 QCoreApplication::sendEvent(); 两个函数,这里可不是随便使用的,这两个函数时又差别的!

 

      1、QCoreApplication::sendEvent();   依据Qt Asistant 里面的讲述。这个函数直接将事件消息直接发送给接受者进行处理,等到事件处理完成后才返回;而且使用它所传递的消息事件是在 栈(stack) 上创建的,也就是说它的内存空间是有编译器来自己主动管理的。

 

      2、QCoreApplication::postEvent();    依据Qt Asistant 里面的讲述,使用这个函数来传递时间消息时。它将事件消息发送到接受者的的消息队列里面,然后马上返回。不须要等到事件处理完成才返回;而且使用它所传递的消息事件是在 堆(heep) 上创建的。也就是说它的内存空间是又程序猿自己管理的,如用 new 创建的变量。

      这两个函数对事件的处理方式就像使用 repaint()  和 paint() 这两个函数对界面进行重画一样。前者直接对界面进行重画操作;后者先将重画事件放到消息队列里面,等到适当的时候在对界面进行重画操作。

 

       在上面的子线程给主线程传递消息的时候使用的就是QCoreApplication::postEvent();  函数。由于这里必须保证在子线程退出之前,若子线程所传递的事件消息还未被主线程处理的话,子线程所传递的消息仍然是可用的。

 

好了。主线程内事件的传递与子线程向主线程传递事件消息的方法就介绍到这里了。至于Qt 的事件传送机制。这里就没有怎么讲了。只是还是建议读者好好去了解一下的好。

这篇关于Qt自定义事件实现及子线程向主线程传送事件消息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1052269

相关文章

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1