1、要创建自定义类型的事件,首先需要定义一个类似于QEvent::KeyPress、QEvent::KeyRelease事件类型,并且该事件类型的值必须大于QEvent::User。然后再子类化QEvent,在子类中实现相关的函数。最后再调用QCoreApplication::postEvent()或者QApplication::sendEvent()。
2、如何定义个事件类型。Qt中提供了[static] int QEvent::registerEventType(int hint = -1)用来定义程序中唯一的事件类型。
3、由于QCoreApplication::postEvent()或者QApplication::sendEvent()是线程安全的,所以在多线程中也可以正常使用。
4、postEvent和sendEvent的区别:
1)sendEvent使用notify()函数直接给receiver发送事件。(不支持多线程、event变量直接在堆栈上生成,在发送事件时,不会删除该事件)
2)postEvent 向事件队列中添加receiver和event,对应异步处理事件。(支持多线程,event必须在堆上分配,因为post事件队列将获得事件的所有权,并在事件被post后删除它)
5、自定义事件可以用来干嘛。
1)用于对象间的通信
#include "widget.h"
#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QEvent>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLineEdit>
//注册两个事件类型
static QEvent::Type g_Widget1_eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
static QEvent::Type g_Widget2_eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
class MyEvent : public QEvent
{
public:
MyEvent(QEvent::Type type):QEvent(type)
{
m_message = "";
}
~MyEvent()
{
qDebug() << __FUNCTION__;
}
void setMessage(const QString &msg)
{
m_message = msg;
}
QString getMessage()const
{
return m_message;
}
private:
QString m_message;
};
class Widget1:public QWidget
{
Q_OBJECT
public:
Widget1()
{
setWindowTitle("Widget1");
QHBoxLayout *layout = new QHBoxLayout;
QPushButton *button = new QPushButton("发送");
layout->addWidget(button);
QLineEdit *edit = new QLineEdit;
layout->addWidget(edit);
connect(button,&QPushButton::clicked,[=]{
// MyEvent *event = new MyEvent(g_Widget1_eventType);
// event->setMessage(edit->text());
// QApplication::postEvent(m_receiver,event);
MyEvent event(g_Widget1_eventType);
event.setMessage(edit->text());
QApplication::sendEvent(m_receiver,&event);
qDebug() << "发送信号";
});
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(layout);
m_label = new QLabel("等待接收信息...");
mainLayout->addWidget(m_label);
setLayout(mainLayout);
}
void setRecevier(QObject *receiver)
{
m_receiver = receiver;
}
protected:
bool event(QEvent *event)
{
if(event->type() == g_Widget2_eventType){
qDebug() << "111";
MyEvent *e = static_cast<MyEvent*>(event);
m_label->setText(e->getMessage());
return true;
}
return QWidget::event(event);
}
private:
QLabel *m_label;
QObject *m_receiver;
};
class Widget2:public QWidget
{
Q_OBJECT
public:
Widget2()
{
setWindowTitle("Widget2");
QHBoxLayout *layout = new QHBoxLayout;
QPushButton *button = new QPushButton("发送");
layout->addWidget(button);
QLineEdit *edit = new QLineEdit;
layout->addWidget(edit);
connect(button,&QPushButton::clicked,[=]{
// MyEvent *event = new MyEvent(g_Widget2_eventType);
// event->setMessage(edit->text());
// QApplication::postEvent(m_receiver,event);
MyEvent event(g_Widget2_eventType);
event.setMessage(edit->text());
QApplication::sendEvent(m_receiver,&event);
qDebug() << "发送信号";
});
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(layout);
m_label = new QLabel("等待接收信息...");
mainLayout->addWidget(m_label);
setLayout(mainLayout);
}
void setRecevier(QObject *receiver)
{
m_receiver = receiver;
}
protected:
bool event(QEvent *event)
{
if(event->type() == g_Widget1_eventType){
qDebug() << "222";
MyEvent *e = static_cast<MyEvent*>(event);
m_label->setText(e->getMessage());
return true;
}
QWidget::event(event);
}
private:
QLabel *m_label;
QObject *m_receiver;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget1 w1;
Widget2 w2;
w1.setRecevier(&w2);
w2.setRecevier(&w1);
w1.show();
w2.show();
return a.exec();
}
#include "main.moc"
2)多线程编程
#include <QApplication>
#include <QThread>
#include <QWidget>
#include <QDebug>
#include <QProgressBar>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QEvent>
//自定义全局事件类型
static const QEvent::Type g_request_eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
static const QEvent::Type g_respond_eventType = static_cast<QEvent::Type>(QEvent::registerEventType());
class DownEvent : public QEvent
{
public:
DownEvent(QEvent::Type type):QEvent(type)
{
}
~DownEvent()
{
qDebug() << __FUNCTION__;
}
void setData(const QString data)
{
m_data = data;
}
QString getData()const
{
return m_data;
}
void setProgress(int data)
{
m_process = data;
}
int getProgress()const
{
return m_process;
}
void setReceiver(QObject *receiver)
{
m_receiver = receiver;
}
QObject *getReceiver()
{
return m_receiver;
}
private:
QString m_data;
int m_process;
QObject *m_receiver;
};
class DownLoadThread : public QThread
{
public:
DownLoadThread(){}
~DownLoadThread()
{
if(isRunning()){
quit();
wait();
}
}
protected:
bool event(QEvent *event)
{
if(event->type() == g_request_eventType){
DownEvent *e = static_cast<DownEvent*>(event);
m_data = e->getData();
m_receiver = e->getReceiver();
if(!this->isRunning())
this->start();
return true;
}
return QThread::event(event);
}
void run()
{
for(int i = 1; i <= 100; ++i){
msleep(500);
DownEvent *event = new DownEvent(g_respond_eventType);
event->setProgress(i);
QApplication::postEvent(m_receiver,event);
}
}
private:
QString m_data;
QObject *m_receiver;
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget()
{
QVBoxLayout *mainLayout = new QVBoxLayout;
QPushButton *button = new QPushButton("下载");
connect(button,&QPushButton::clicked,[=]{
DownEvent *event = new DownEvent(g_request_eventType);
event->setData("xxxx.txt");
event->setReceiver(this);
QApplication::postEvent(m_receiver,event);
button->setEnabled(false);
});
mainLayout->addWidget(button);
m_bar = new QProgressBar;
connect(m_bar,&QProgressBar::valueChanged,[=](int value){
if(m_bar->maximum() == value)
button->setEnabled(true);
});
m_bar->setRange(0,100);
mainLayout->addWidget(m_bar);
setLayout(mainLayout);
}
void setReceiver(QObject *receiver)
{
m_receiver = receiver;
}
bool event(QEvent *event)
{
if(event->type() == g_respond_eventType){
DownEvent *e = static_cast<DownEvent*>(event);
m_process = e->getProgress();
qDebug() << m_process;
m_bar->setValue(m_process);
return true;
}
return QWidget::event(event);
}
private:
int m_process;
QObject *m_receiver;
QProgressBar *m_bar;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
DownLoadThread thread;
Widget w;
w.show();
w.setReceiver(&thread);
return a.exec();
}
#include "main.moc"