目录
一、Qt提供5个级别的事件处理和过滤 (从后到先):
1、重新实现事件函数。
2、重新实现QObject::event().
3、安装事件过滤器
4、在 QApplication 上安装事件过滤器。
5、重新实现QApplication 的 notify()方法.
二、event 与 Even Filter
1. event() 简介
2. event 返回值的作用
3. 事件过滤器(Even Filter)
比如: mousePressEvent(), keyPressEvent(), paintEvent() 。
这是最常规的事件处理方法。
这一般用在Qt没有提供该事件的处理函数时。也就是,我们增加新的事件时。
installEventFilter() -- bool eventFilter(QObject *target, QEvent *event)
这之所以被单独列出来是因为: QApplication 上的事件过滤器将捕获应用程序的所有事件,而且***个获得该事件。也就是说事件在发送给其它任何一个event filter之前发送给QApplication的event filter。
Qt使用 notify()来分发事件。要想在任何事件处理器捕获事件之前捕获事件,***的方法就是重新实现QApplication 的 notify()方法。
event 函数的作用就在于 事件的分发,在 even filter 之后执行
bool myWidget::event(QEvent *e)
{
if (e->type() == QEvent::KeyPress)
{
//将QEvent对象转换为真正的QKeyEvent对象
QKeyEvent *keyEvent = static_cast(e);
if (keyEvent->key() == Qt::Key_Tab)
{
qDebug() << "You press tab.";
return true;
}
}
//按照原来的流程来进行事件的分发
return QWidget::event(e);
}
如果传入的事件已被识别并且处理,则需要返回 true,否则返回 false。如果返回值是 true,那么 Qt 会认为这个事件已经处理完毕,不会再将这个事件发送给其它对象,而是会继续处理事件队列中的下一事件。
若返回 父类的 event,即 return QWidget::event(e); 则还会调用 父组件。
Qt系统在处理事件时,有一种机制叫 事件传播机制。也就是说,在子组件(比如说一个QButton)中发生的事件,调用了子组件的event函数之后,还会 调用父组件(比如说QWidget)的 event 函数。event函数的 返回值 就用于控制这样的一个过程。
需要注意的是,重写event函数之后最好返回父类的event函数来处理其他的事件分发,不然就只能处理自己定义的事件。
bool myTextEdit::event(QEvent *e)
{
if (e->type() == QEvent::KeyPress)
{
//将QEvent对象转换为真正的QKeyEvent对象
QKeyEvent *keyEvent = static_cast(e);
if (keyEvent->key() == Qt::Key_Tab)
{
qDebug() << "You press tab.";
return true;
}
}
//直接返回false
return false;
}
在这个例子中,因为没有调用父类QTextEdit的event函数,所以只能处理Tab的情况,你再按其他按键就啥反应都没有了。同样,事件也不能进行传播。
virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );
函数的返回值也是bool类型,作用跟even函数类似,返回true为不再转发,false则让其继续被处理
class MainWindow : public QMainWindow
{
public:
MainWindow();
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
QTextEdit *textEdit;
};
MainWindow::MainWindow()
{
textEdit = new QTextEdit;
setCentralWidget(textEdit);
textEdit->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == textEdit)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast(event);
qDebug() << "you press" << keyEvent->key();
//事件不再进行传播,拦截
return true;
}
else
{
return false;//继续传播
}
}
else
{
//当不确定是否继续传播时,按照父类的方法来处理
//即调用父类的evenFilter函数
return QMainWindow::eventFilter(obj, event);
//也可直接 return false; 不进行拦截, 且不继续传播
}
}