Qt 可以在程序中自主发送事件
阻塞型事件发送
- 事件发送后需要等待事件处理完成
非阻塞型事件发送
- 事件发送后立即返回
- 事件被分发到事件队列等待处理
QApplication 类提供了事件发送的静态成员函数
阻塞型发送函数:
- bool sendEvent(QObject* receiver,QEvent* event);
非阻塞型发送函数:
- bool postEvent(QObject* receiver,QEvent* event);
注意事项
sendEvent 中事件对象的生命周期由 Qt 程序管理
- 同时支持栈事件对象和堆事件对象的发送
postEvent 中事件对象的生命周期由 Qt 程序管理
- 只能发送堆事件对象
- 事件处理后由 Qt 平台进行销毁
使用 sendEvent 发送事件对象
小贴士:消息发送过程可以理解为:在 sendEvent 函数内部直接调用 Qt 对象的 event() 事件处理函数。
使用 postEvent 发送事件对象
在程序中发送事件
Widget.h
class Widget : public QWidget
{
Q_OBJECT
private:
QPushButton m_Btn;
private slots:
void onPushButtonClicked();
protected:
void testSendEvent();
void testPostEvent();
bool event(QEvent* e);
public:
Widget(QWidget* parent = nullptr);
~Widget();
};
Widget.cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
m_Btn.setParent(this);
connect(&m_Btn, &QPushButton::clicked, this, &Widget::onPushButtonClicked);
}
void Widget::onPushButtonClicked()
{
testSendEvent();
// testPostEvent();
}
void Widget::testSendEvent()
{
QMouseEvent me(QEvent::MouseButtonDblClick,QPointF(1, 1), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
qDebug() << "before send event";
QApplication::sendEvent(this, &me);
qDebug() << "after send event";
}
void Widget::testPostEvent()
{
QMouseEvent *me = new QMouseEvent(QEvent::MouseButtonDblClick,QPointF(1, 1), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
qDebug() << "before post event";
QApplication::postEvent(this, me);
qDebug() << "after post event";
}
bool Widget::event(QEvent *e)
{
if(e->type() == QEvent::MouseButtonDblClick)
qDebug() << "event : " << e;
return QWidget::event(e);
}
Widget::~Widget()
{
}
首先测试 sendEvent,结果如下所示
测试 postEvent,结果如下所示
Qt 可以自定义新的事件类
自定义的事件类必须继承自 QEvent
自定义的事件类必须拥有全局唯一的 Type 值
程序中必须提供处理自定义事件对象的方法
自定义事件类
1. 将 QEvent 作为父类继承
2. 指定全局唯一的 Type 值
Qt 中事件的 Type 值
每个事件类都具有全局唯一的 Type 值
自定义事件类的 Type 值也需要自定义
自定义事件类使用 QEvent::User 之后的值作为 Type 值
程序中保证 QEvent::User + Value 全局唯一即可
处理自定义事件的方法
1. 将事件过滤器安装到目标对象
- 在 EventFilter() 函数中编写自定义事件的处理逻辑
2. 在目标对象的类中重写事件处理函数
- 在 event() 函数中编写自定义事件的处理逻辑
发送和处理自定义事件
StringEvent.h
class StringEvent : public QEvent
{
private:
QString m_data;
public:
explicit StringEvent(QString data = 0);
const static Type TYPE = static_cast<Type>(QEvent::User + 0xFF);
void setData(QString data);
QString data();
signals:
};
StringEvent.cpp
StringEvent::StringEvent(QString data) : QEvent(TYPE)
{
m_data = data;
}
void StringEvent::setData(QString data)
{
m_data = data;
}
QString StringEvent::data()
{
return m_data;
}
Widget.h
class Widget : public QWidget
{
Q_OBJECT
private:
QLineEdit m_edit;
protected:
bool event(QEvent* e);
bool eventFilter(QObject* obj, QEvent* e);
public:
Widget(QWidget* parent = nullptr);
~Widget();
};
Widget.cpp
Widget::Widget(QWidget *parent)
: QWidget(parent), m_edit(this)
{
m_edit.installEventFilter(this);
resize(600, 400);
}
bool Widget::eventFilter(QObject *obj, QEvent *e)
{
if((obj == &m_edit) && e->type() == StringEvent::TYPE)
{
StringEvent* se = dynamic_cast<StringEvent*>(e);
qDebug() << "receive data : " << se->data();
m_edit.insert(se->data());
return true;
}
return QWidget::eventFilter(obj, e);
}
bool Widget::event(QEvent *e)
{
if(e->type() == QEvent::MouseButtonDblClick)
{
StringEvent se("liujie");
qDebug() << "before send event";
QApplication::sendEvent(&m_edit, &se);
qDebug() << "after send event";
}
return QWidget::event(e);
}
Widget::~Widget()
{
}
程序运行结果如下所示
为什么要自定义事件类?
需要拓展一个已有组件类的功能
需要开发一个全新功能的组件类
需要向一个第三方的组件类发送消息