Qt自定义事件
事件既可以用在多线程,也可以是单线程中对象间通讯
为什么使用事件?与信号槽的区别:
1.事件的分发既可以是同步的,又可以是异步的,槽的回调总是同步的
2.事件可以使用过滤器
3.事件可以携带自定义数据;信号槽传递数据,某些数据类型需要进行qRegisterMetaType注册
如何使用自定义事件
1.一个继承自QEvent的类
2.自定义事件的type来确定这个自定义事件
注意:需要和已经存在的type不能重复,系统保留了0-999的值,Qt定义了自定义事件的两个边界值:QEvent::User(1000)和
QEvent::MaxUser(65535)。Qt提供一个静态的自定义事件注册函数registerEventType()
3.自定义事件的发送
两种发送方式:sendEvent()和postEvent()两中函数,两者区别,sendEvent()是直接发送给接受者,发送之后,event对象并不会被销毁,通常是在栈上创建event对象;postEvent()是将事件加入到事件队列中,由事件循环处理,需要在堆上创建event对象,事件根据post顺序进行处理,可以指定高优先级进行优先处理,默认优先级为Qt::NormalEventPriority。sendPostedEvents()函数可以将参数中的类型事件立即发送给接受者进行处理,窗口系统的事件不由这个函数,而是postEvents()函数。
4.重写event()函数。这里也可以重写QObject::customEvent()函数。
下面是一个简单线程的自定义事件显示时间的例子
1.首先定义一个继承自QEvent的类
#ifndef CUSTOMEVENT_H
#define CUSTOMEVENT_H
#include <QEvent>
#include <QString>
class CustomEvent : public QEvent
{
public:
CustomEvent(const QString &msg);
static QEvent::Type rtEvType();
static QEvent::Type m_eventType;
QString m_msg;
};
#endif // CUSTOMEVENT_H
#include "customevent.h"
QEvent::Type CustomEvent::m_eventType = (QEvent::Type)QEvent::registerEventType(); //注册自定义事件的type
CustomEvent::CustomEvent(const QString &msg):
QEvent(rtEvType()), m_msg(msg)
{
}
QEvent::Type CustomEvent::rtEvType()
{
return m_eventType;
}
2.写一个简单的线程类来发送这个自定义事件
#ifndef CUSTOMTHREAD_H
#define CUSTOMTHREAD_H
#include <QThread>
class CustomThread : public QThread
{
Q_OBJECT
public:
explicit CustomThread(QObject *receiver);
~CustomThread();
void run();
QObject *m_receiver;
};
#endif // CUSTOMTHREAD_H
#include "customthread.h"
#include <QDateTime>
#include <QCoreApplication>
#include "customevent.h"
CustomThread::CustomThread(QObject *receiver) :
m_receiver(receiver)
{
}
CustomThread::~CustomThread()
{
wait();
}
void CustomThread::run()
{
while(1) {
QThread::msleep(1000);
CustomEvent *ce = new CustomEvent(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")); //获取当前时间的自定义事件
QCoreApplication::postEvent(m_receiver, ce); //发送事件
}
}
3.在主线程中重写event处理自定义事件#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QLabel>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
bool event(QEvent *e);
private:
Ui::Widget *ui;
QLabel *m_label;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include "customthread.h"
#include "customevent.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
m_label = new QLabel(this);
CustomThread *thread = new CustomThread(this);
thread->start();
}
Widget::~Widget()
{
delete ui;
}
bool Widget::event(QEvent *e)
{
if(e->type() == CustomEvent::rtEvType()) {
CustomEvent *ce = (CustomEvent*)e;
m_label->setText(ce->m_msg);
m_label->adjustSize();
e->accept();
return true;
}
return QWidget::event(e); //自定义事件以外的事件都由QWidget::event()处理
}