Qt自定义事件实现及子线程向主线程传送事件消息
近期在又一次學(xué)習(xí)Qt的時(shí)候,由于要涉及到子線程與主線程傳遞消息,所以便琢磨了一下。順便把有用的記錄下來,方便自己以后查詢及各位同仁的參考!
特此聲明,本篇博文主要講述有用的,也就是直接說明怎么實(shí)現(xiàn),就不打算陳述一大堆理論啦,只是,還是建議大家去查查對應(yīng)的理論比較好。這樣能對Qt的消息傳送機(jī)制的理解更加深入。
依據(jù)網(wǎng)上大多數(shù)人的資料,要實(shí)現(xiàn)自己定義消息,須要從QEvent 派生一個(gè)自己定義的事件;事實(shí)上也能夠不須要,僅僅要使用QEvent::Type自己定義一個(gè)事件即可了。
在這里,本人把兩種實(shí)現(xiàn)方法都在這里講述一下!
?
一、這里先講述使用 QEvent::Type 定義一個(gè)自己定義事件
????? 1、新建一個(gè)新的project “myEvent” 。在 ui?界面加入一個(gè)button,并未button加入?onclick() 響應(yīng)函數(shù)。
????? 2、在 widget.h 頭文件使用 QEvent::Type 定義兩個(gè)自己定義事件。
????? 3、又一次實(shí)現(xiàn)?event() 虛函數(shù)
<span style="color:#000000">bool event(QEvent* e);</span>????? 4、加入 #include<QEvent>
?
整個(gè)頭文件例如以下:
?
<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()?靜態(tài)函數(shù)為剛才兩個(gè)自己定義事件注冊值。
????? 6、又一次實(shí)現(xiàn) event()? 函數(shù) 。
?
????? 7、在?button響應(yīng)函數(shù)里面發(fā)送時(shí)間消息。
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>編譯執(zhí)行后界面例如以下:
?
?
?
二、從 QEvent 派生一個(gè)自己定義事件類,類名取為 myEvent 。
?
????? 1、myevent.h 頭文件例如以下。里面自己定義了三個(gè)自己定義事件,分別為?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響應(yīng)函數(shù)例如以下:
?
<span style="color:#000000">void Widget::on_pushButton_clicked() {myEvent e(myEvent::m_event1);QCoreApplication::sendEvent(this, &e); }</span>5、改動 widget.cpp 文件中面的?event() 函數(shù)例如以下:
?
?
<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);}
然后又一次編譯執(zhí)行,效果例如以下:
?
?
三 、?前面講的都是在主線程里面?zhèn)鬟f事件消息,接下來講述怎樣?在子線程里面 往主線程?傳遞事件消息。
????? 1、從 QThread?派生一個(gè)自己定義事件類,類名取為 myThread , 并又一次實(shí)現(xiàn)?run() 虛函數(shù)。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 里面又一次實(shí)現(xiàn)?run() 函數(shù)。在里面實(shí)現(xiàn)向主線程發(fā)送事件消息,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 頭文件, 然后定義一個(gè)子線程對象,?例如以下:
?
#include"mythread.h"
?
myThread*m_pThread;
?
??????4、在堆內(nèi)存里面為m_pThread開辟一個(gè)內(nèi)存空間,例如以下:
?
<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? 界面?加入還有一個(gè)button。并為它加入?onclick() 事件響應(yīng)。然后在里面執(zhí)行子線程,例如以下:
?
?
<span style="color:#000000">void Widget::on_pushButton_2_clicked() {m_pThread->start(); } </span>編譯執(zhí)行程序,效果例如以下:
?
?
四、QCoreApplication::postEvent(); 和?QCoreApplication::sendEvent();???? 的差別。
在前面的程序中發(fā)送?事件消息 的時(shí)候用到了?QCoreApplication::postEvent(); 和?QCoreApplication::sendEvent();?兩個(gè)函數(shù),這里可不是隨便使用的,這兩個(gè)函數(shù)時(shí)又差別的!
?
????? 1、QCoreApplication::sendEvent();???依據(jù)Qt Asistant 里面的講述。這個(gè)函數(shù)直接將事件消息直接發(fā)送給接受者進(jìn)行處理,等到事件處理完成后才返回;而且使用它所傳遞的消息事件是在 棧(stack)?上創(chuàng)建的,也就是說它的內(nèi)存空間是有編譯器來自己主動管理的。
?
????? 2、QCoreApplication::postEvent();?? ?依據(jù)Qt Asistant 里面的講述,使用這個(gè)函數(shù)來傳遞時(shí)間消息時(shí)。它將事件消息發(fā)送到接受者的的消息隊(duì)列里面,然后馬上返回。不須要等到事件處理完成才返回;而且使用它所傳遞的消息事件是在?堆(heep)?上創(chuàng)建的。也就是說它的內(nèi)存空間是又程序猿自己管理的,如用?new 創(chuàng)建的變量。
????? 這兩個(gè)函數(shù)對事件的處理方式就像使用 repaint()? 和 paint() 這兩個(gè)函數(shù)對界面進(jìn)行重畫一樣。前者直接對界面進(jìn)行重畫操作;后者先將重畫事件放到消息隊(duì)列里面,等到適當(dāng)?shù)臅r(shí)候在對界面進(jìn)行重畫操作。
?
?????? 在上面的子線程給主線程傳遞消息的時(shí)候使用的就是QCoreApplication::postEvent();? 函數(shù)。由于這里必須保證在子線程退出之前,若子線程所傳遞的事件消息還未被主線程處理的話,子線程所傳遞的消息仍然是可用的。
?
好了。主線程內(nèi)事件的傳遞與子線程向主線程傳遞事件消息的方法就介紹到這里了。至于Qt 的事件傳送機(jī)制。這里就沒有怎么講了。只是還是建議讀者好好去了解一下的好。
總結(jié)
以上是生活随笔為你收集整理的Qt自定义事件实现及子线程向主线程传送事件消息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消息中间件:RocketMQ 介绍(特性
- 下一篇: Docker 方式安装、运行 Nexus