博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Qt自定义事件实现及子线程向主线程传送事件消息
阅读量:4303 次
发布时间:2019-05-27

本文共 5367 字,大约阅读时间需要 17 分钟。

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

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

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

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

 

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

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

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

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

bool event(QEvent* e);

      4、加入 #include<QEvent>

 

整个头文件例如以下:

 

#ifndef WIDGET_H#define WIDGET_H#include 
#include
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

 

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

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

 

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

widget.cpp 文件例如以下:

 

#include "widget.h"#include "ui_widget.h"#include 
#include
#include
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); myEvent1 = static_cast
(QEvent::registerEventType(-1)); myEvent2 = static_cast
(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));}

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

 

 

 

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

 

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

 

#ifndef MYEVENT_H#define MYEVENT_H#include 
class myEvent : public QEvent{public: myEvent(Type e);public: static Type m_event1; static Type m_event2; static Type m_event3;};#endif // MYEVENT_H

 

 

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

myevent.cpp 文件例如以下:

 

#include "myevent.h"#include 
QEvent::Type myEvent::m_event1 = static_cast
(QEvent::registerEventType());QEvent::Type myEvent::m_event2 = static_cast
(QEvent::registerEventType());QEvent::Type myEvent::m_event3 = static_cast
(QEvent::registerEventType());myEvent::myEvent(Type e):QEvent(e){}

 

 

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

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

 

void Widget::on_pushButton_clicked(){    myEvent e(myEvent::m_event1);    QCoreApplication::sendEvent(this, &e);}

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

 

 

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;

 

 

 }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 头文件例如以下:

 

#ifndef MYTHREAD_H#define MYTHREAD_H#include 
class myThread : public QThread{ Q_OBJECTpublic: explicit myThread(QObject *parent = 0);signals:public slots:protected: void run();};#endif // MYTHREAD_H 

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

 

 

#include "mythread.h"#include "myevent.h"#include 
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();}

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

 

#include"mythread.h"

 

myThread*m_pThread;

 

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

 

Widget::Widget(QWidget *parent) :    QWidget(parent),    ui(new Ui::Widget){    ui->setupUi(this);    m_pThread = new myThread(this);   。。

 

。。。。 }</span>

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

 

 

void Widget::on_pushButton_2_clicked(){    m_pThread->start();}

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

 

 

四、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 的事件传送机制。这里就没有怎么讲了。只是还是建议读者好好去了解一下的好。

转载地址:http://zclws.baihongyu.com/

你可能感兴趣的文章
nginx屏蔽ip
查看>>
什么是FastCGI和FastCGI的优点
查看>>
如何设置开机自启动程序
查看>>
Nginx+FastCGI运行原理
查看>>
Spawn-fcgi与PHP-FPM区别
查看>>
PHP与PHP-FPM的配置与优化
查看>>
配置Nginx来支持PHP----重点介绍Nginx如何通过PHP_FPM的FastCGI进程对PHP进行解析处理。
查看>>
测试Nginx对PHP的解析功能--查看PHP安装配置以及功能列表统计信息
查看>>
优化Nginx中FastCGI参数的实例
查看>>
Windows如何查看端口占用
查看>>
phpstrom如何配置git
查看>>
phpStorm中如何使用git
查看>>
3种PHP连接MYSQL数据库的常用方法
查看>>
linux命令(6) zip/unzip及tar压缩与解压文件命令笔记
查看>>
linux命令(7)ubuntu的vim命令用法
查看>>
使用nginx配置多个php-fastcgi负载均衡
查看>>
CURL抓取网页内容并用正则提取。
查看>>
Ngin的配置文件nginx.conf完整配置说明(包括fastcgi和负载均衡设置)
查看>>
浏览器显示网页的机制
查看>>
CSS基础知识
查看>>