事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。
如上所述,event()函数主要用于事件的分发。所以,如果你希望在事件分发之前做一些操作,就可以在派生类中重写这个event()函数了。例如,我们希望在一个QWidget组件中监听 tab 键的按下,那么就可以继承QWidget,并重写它的event()函数,来达到这个目的:
bool MyWidget::event(QEvent *e)
{
if (e->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);//强制类型转换
if (keyEvent->key() == Qt::Key_Tab) {
qDebug() << "You press tab.";
return true;
}
}
return QWidget::event(e);//必要的,继续执行直接基类的event函数重新处理其他事件
}
MyWidget是一个QWidget的派生类。我们重写了它的event()函数,这个函数有一个QEvent对象作为参数,也就是需要转发的事件对象。函数返回值是 bool 类型。
· 如果传入的事件已被识别并且处理,则需要返回 true,否则返回 false。如果返回值是 true,那么 Qt 会认为这一个事件已经处理完毕,不会再将这一个事件发送给其它对象,而是会继续处理事件队列中的下一事件。
· 在event()函数中,调用事件对象的accept()和ignore()函数是没有作用的,不会影响到事件的传播。
我们可以通过使用QEvent::type()函数可以检查事件的实际类型,其返回值是QEvent::Type类型的枚举。我们处理过自己感兴趣的事件之后,可以直接返回 true,表示我们已经对此事件进行了处理;对于其它我们不关心的事件,则需要调用直接基类的event()函数继续分发,否则这个组件就只能处理我们定义的事件了。
再比如:对mybutton控件的event函数也可以进行重写:
//mybutton.h
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QWidget>
#include<QPushButton>
class myButton : public QPushButton
{
Q_OBJECT
public:
explicit myButton(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *ev);
bool event(QEvent *event);
signals:
};
#endif // MYBUTTON_H
//mybutton.cpp
#include "mybutton.h"
#include<QPushButton>
#include<QMouseEvent>
#include<QDebug>
myButton::myButton(QWidget *parent) : QPushButton(parent)
{
}
void myButton::mousePressEvent(QMouseEvent *ev)
{
if(ev->button()==Qt::LeftButton)
{
qDebug()<<"按下的是左键";
//ev->ignore();//事件会继续传递,传递给谁呢?这里注意,是传递给父组件!!
}
else
{
QPushButton::mousePressEvent(ev);
//事件的忽略,事件传递给父类去处理
}
}
bool myButton::event(QEvent *e)
{
if (e->type() == QEvent::MouseButtonPress) {
QMouseEvent *mouseEvent = static_cast< QMouseEvent *>(e);//强制类型转换
if (mouseEvent->button() == Qt::LeftButton||Qt::RightButton||Qt::MidButton) {
qDebug() << "myButton::event";
return QPushButton::event(e);
}
}
return QPushButton::event(e);//必要的,继续执行基类的event函数重新处理其他事件
}