博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Qt笔记】event()
阅读量:6890 次
发布时间:2019-06-27

本文共 2840 字,大约阅读时间需要 9 分钟。

hot3.png

前面的章节中我们曾经提到event()函数。事件对象创建完毕后,Qt 将这个事件对象传递给QObjectevent()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。

 

如上所述,event()函数主要用于事件的分发。所以,如果你希望在事件分发之前做一些操作,就可以重写这个event()函数了。例如,我们希望在一个QWidget组件中监听 tab 键的按下,那么就可以继承QWidget,并重写它的event()函数,来达到这个目的:

bool CustomWidget::event(QEvent *e){    if (e->type() == QEvent::KeyPress) {        QKeyEvent *keyEvent = static_cast
(e); if (keyEvent->key() == Qt::Key_Tab) { qDebug() << "You press tab."; return true; } } return QWidget::event(e);}

CustomWidget是一个普通的QWidget子类。我们重写了它的event()函数,这个函数有一个QEvent对象作为参数,也就是需要转发的事件对象。函数返回值是 bool 类型。如果传入的事件已被识别并且处理,则需要返回 true,否则返回 false。如果返回值是 true,并且,该事件对象设置了accept(),那么 Qt 会认为这个事件已经处理完毕,不会再将这个事件发送给其它对象,而是会继续处理事件队列中的下一事件。注意,在event()函数中,调用事件对象的accept()ignore()函数是没有作用的,不会影响到事件的传播。

我们可以通过使用QEvent::type()函数可以检查事件的实际类型,其返回值是QEvent::Type类型的枚举。我们处理过自己感兴趣的事件之后,可以直接返回 true,表示我们已经对此事件进行了处理;对于其它我们不关心的事件,则需要调用父类的event()函数继续转发,否则这个组件就只能处理我们定义的事件了。为了测试这一种情况,我们可以尝试下面的代码:

bool CustomTextEdit::event(QEvent *e){    if (e->type() == QEvent::KeyPress) {        QKeyEvent *keyEvent = static_cast
(e); if (keyEvent->key() == Qt::Key_Tab) { qDebug() << "You press tab."; return true; } } return false;}

CustomTextEditQTextEdit的一个子类。我们重写了其event()函数,却没有调用父类的同名函数。这样,我们的组件就只能处理 Tab 键,再也无法输入任何文本,也不能响应其它事件,比如鼠标点击之后也不会有光标出现。这是因为我们只处理的KeyPress类型的事件,并且如果不是KeyPress事件,则直接返回 false,鼠标事件根本不会被转发,也就没有了鼠标事件。

通过查看QObject::event()的实现,我们可以理解,event()函数同前面的章节中我们所说的事件处理器有什么联系:

//!!! Qt5bool QObject::event(QEvent *e){    switch (e->type()) {    case QEvent::Timer:        timerEvent((QTimerEvent*)e);        break;    case QEvent::ChildAdded:    case QEvent::ChildPolished:    case QEvent::ChildRemoved:        childEvent((QChildEvent*)e);        break;    // ...    default:        if (e->type() >= QEvent::User) {            customEvent(e);            break;        }        return false;    }    return true;}

这是 Qt 5 中QObject::event()函数的源代码(Qt 4 的版本也是类似的)。我们可以看到,同前面我们所说的一样,Qt 也是使用QEvent::type()判断事件类型,然后调用了特定的事件处理器。比如,如果event->type()返回值是QEvent::Timer,则调用timerEvent()函数。可以想象,QWidget::event()中一定会有如下的代码:

switch (event->type()) {    case QEvent::MouseMove:        mouseMoveEvent((QMouseEvent*)event);        break;    // ...}

事实也的确如此。timerEvent()mouseMoveEvent()这样的函数,就是我们前面章节所说的事件处理器 event handler。也就是说,event()函数中实际是通过事件处理器来响应一个具体的事件。这相当于event()函数将具体事件的处理“委托”给具体的事件处理器。而这些事件处理器是 protected virtual 的,因此,我们重写了某一个事件处理器,即可让 Qt 调用我们自己实现的版本。

由此可以见,event()是一个集中处理不同类型的事件的地方。如果你不想重写一大堆事件处理器,就可以重写这个event()函数,通过QEvent::type()判断不同的事件。鉴于重写event()函数需要十分小心注意父类的同名函数的调用,一不留神就可能出现问题,所以一般还是建议只重写事件处理器(当然,也必须记得是不是应该调用父类的同名处理器)。这其实暗示了event()函数的另外一个作用:屏蔽掉某些不需要的事件处理器。正如我们前面的CustomTextEdit例子看到的那样,我们创建了一个只能响应 tab 键的组件。这种作用是重写事件处理器所不能实现的。

 

转载于:https://my.oschina.net/daowuming/blog/723979

你可能感兴趣的文章
在企业环境下实现禁止使用USB的高安全措施
查看>>
乐在其中设计模式(C#) - 单例模式(Singleton Pattern)
查看>>
SVN提示文件被锁住以及Unlocker软件的使用
查看>>
MySQL Study案例之--MySQL体系和存储引擎
查看>>
php注入之完全版
查看>>
高效的生产力
查看>>
岁月划过生命线(从0到阿里)
查看>>
七招搞定微信朋友圈营销
查看>>
mysql 查看表
查看>>
Centos5 搭建独立版本库SVN
查看>>
云场景实践研究第6期:游族网络
查看>>
记录由Equal基础知识引起的内存泄露
查看>>
Android:Sensor传感器
查看>>
Eclipse配置实现定制登录界面
查看>>
NO.1 进入IT世界
查看>>
Exceeded maximum number of retries. Exceeded max scheduling attempts 3 for instance
查看>>
Asp.net mvc 3.0新特性-浅析1
查看>>
Hadoop FSDataInputStream 流定位的例子
查看>>
在OWA页面中,增加忘记密码项
查看>>
vim 配置详解
查看>>