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_OBJECT
public:
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 Creator开发的程序提升到管理员权限运行
- Qt 积累
- Qt中基类widget的各个事件函数中包含了ignore()的调用
- QT-事件详解2
- Qt-事件过滤器eventFilter概念及使用方法实例
- QT消息/事件循环机制与多线程的关系
- Qt消息机制和事件概述(一)
- QT中父子窗口事件传递与事件过滤器
- qt中new与delete使用示例
- 【QT】Qt项目demo:数据在ui界面上显示,鼠标双击可弹窗显示具体信息
- 【QT】Qt creator连接MySQL数据库 - 增删改查
- 【QT】Qt使用QJson生成json文件并保存
- Qt音视频开发19-vlc内核各种事件通知
- Qt开发经验小技巧256-260
- Qt编写物联网管理平台37-逻辑设计
- Qt编写可视化大屏电子看板系统28-模块6送检合格
- Qt编写地图综合应用58-兼容多浏览器内核
- Qt通用方法及类库9
- Qt编写自定义控件7-自定义可拖动多边形
- qt widget设置Qt::FramelessWindowHint和Qt::WA_TranslucentBackground, 会出现一个bug: 在最小化后还原时界面停止刷新(Qt5.1解决了这个问题。但实际Qt5.7还有这个问题)
- accept()函数用来告诉Qt,事件处理函数“接收”了这个事件,不要再传递;ignore()函数则告诉Qt,事件处理函数“忽略”了这个事件,需要继续传递(看一下QWidget::mousePressEvent的实现,最为典型。如果希望忽略事件,只要调用父类的响应函数即可)
- QT中|Qt::Tool类型窗口自动退出消息循环问题解决(setQuitOnLastWindowClosed必须设置为false,最后一个窗口不显示的时候,程序会退出消息循环)
- Qt之QStackedLayout
- Qt编程之信号与槽-------unresolved external symbol "public: virtual struct QMetaObject const * __thiscall XX::metaObject(void)const
- Qt ------ 覆盖eventFilter(),捕获组件事件,事件处理
- 【正点原子Linux连载】第十三章 多媒体 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
- 【正点原子Linux连载】 第十九章 CAN Bus 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
- Qt connect parent widget 连接父控件的信号槽