免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4362 | 回复: 0
打印 上一主题 下一主题

Qt Event 乱弹 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-24 20:30 |只看该作者 |倒序浏览
Qt 的应用程序都是事件驱动的。

在Qt中,所有的Event对象都是由从QEvent类派生出来的类来描述的。通过调用QObject::event()函数来发送到从QObject继承出来的Qt对象,这个对象会有相应的方法来处理这个事件。

事件的来源主要有两种:

1, 系统产生的
通常是window system把从系统得到的消息,比如鼠标按键,键盘按键等, 放入系统的消息队列中. Qt事件循环的时候读取这些事件,转化为QEvent,再依次处理.

2, Qt应用程序程序自身产生的
程序产生事件有两种方式, 一种是调用QApplication::postEvent(). 例如QWidget::update()函数,当需要重新绘制屏幕时,程序调用update()函数,new出来一个paintEvent,调用QApplication::postEvent(),将其放入Qt的消息队列中,等待依次被处理. 另一种方式是调用sendEvent()函数. 这时候事件不会放入队列, 而是直接被派发和处理, QWidget::repaint()函数用的就是这种方式.

但是对于Qt来说,它并不需要区分这些事件的来源,他们都会采用同样的方式来一致的处理。而且几乎每一种事件都会有一个特定的类相对应。如:QMouseEvent对应鼠标事件,QKeyEvent对应键盘就十分,QCloseEvent对应窗口关闭事件,等等。

QtEvent 的类型很多, 常见的 event类型如下:

** 键盘事件: 按键按下(press)和松开(release)
** 鼠标事件:鼠标按键的按下(press)和松开(release),鼠标移动(move),双击(double click)
** 拖放事件: 用鼠标进行拖放(drag and drop)
** 滚轮事件: 鼠标滚轮滚动(wheel event)
** 绘屏事件: 重绘屏幕的某些部分(paint)
** 定时事件: 定时器到时(timer)
** 焦点事件: 键盘焦点移动(focus)
** 进入和离开事件: 鼠标移入widget之内,或是移出(focus in & focus out)
** 大小改变事件: widget的大小改变(resize)
** 显示和隐藏事件: widget显示和隐藏(show & hide)
** 窗口事件: 窗口是否为当前窗口
** 还有一些不太常见的event,比如socket事件,剪贴板事件,字体改变,布局改变等

在大多数情况下,Qt类都是通过一个虚函数来实现对事件的响应的,这样对于继承出来的类来说,就有机会重新实现这个事件的响应方法。比如,我们会经常写QWidget::paintEvent(…)函数来对一个widget做paint处理,其实,这就是在响应一个QPaintEvent事件。

事件发送的方法主要有两种:

1, send event:
这可以通过调用QCoreApplication::sendEvent(QObject* receiver, QEvent* event)这个函数来实现。当通过这个函数调用来发送一个事件的时候,事件响应函数立刻就会被调用到,也就是说,这是一个同步调用。

2, post event:
这可以通过调用QCoreApplication::postEvent(QObject* receiver, QEvent* event)这个函数来实现。当通过这个函数调用来发送一个事件的事件,事件响应函数并没有立刻被调用,而是把事件先放到一个事件队列里面去,然后在Qt的Event Loop下次才会检索到这个event,然后调用相应的事件处理函数。
Qt的event loop还有这样一个特性,他会把相同的event进行合并,以避免这些事件被执行多次。如:你一次post了多个QPaintEvent事件,那么Qt会把这些事件合并成为一个QPaintEvent事件,这样做的好处是节约系统资源,只paint一次就可以了,而且还有效的避免的界面的闪烁。

Qt有以下几种不同的事件处理方法:

1, Qt的类已经实现的那些事件处理方法,如:paintEvent(..), mousePressEvent(..), keyPressEvent(..), 等等。这些事件处理函数都是虚函数,我们可以在自己定义的类里面重新实现这些函数来处理相应的事件。这是最经常实用,这是最通用,最容易的方法。

2, 重新实现QCoreApplication::notify(QObject* receiver, QEvent* event)函数。这也是一个非常强大,而且可以对事件进行完全控制的方法。但是在一个应用程序中,只能有一个QCoreApplication类(或者是它的子类)的实例存在。

3, 在QCoreApplication(或者其子类)的实例上面安装event filter来处理事件。这样的event filter可以处理到所有的widget event,所有它和重写QCoreApplication::notify函数功能一样强大。另外,在一个应用程序中可以有多个全局性的event filter。需要注意的是,application的event filter只有在那些在主线程中的对象调用。

4, 重新实现QObject::event函数。在这个函数中,你能获得更多的事件控制权限,它会在一个对象的特定事件处理函数之前被调用。比如说:paintEvent, keyPressEvent,等等。

5, 给一个对象安装一个event filter,这个filter将会获得这个对象的所有事件调用。

事件运行机制:

有两种event调度方式,一种是同步的, 一种是异步.

** 当应用程序的main函数调用QCoreApplication的exec()方法是,应用程序进入Qt的主事件循环,它从事件队列中取出本窗口及系统事件,然后把他们打包成相应的QEvent的子类对象,并且使用函数QCoreApplication::notify函数发送事件到相应的QObject对象。在这个主事件循环中,是异步处理的。

** QApplication::sendEvent()的时候, 消息会立即被处理,是同步的. 实际上QApplication::sendEvent()是通过调用QApplication::notify(), 直接进入了事件的派发和处理环节
Event Filter:

一个event filter是一个能够接收所有发送到这个对象上面的事件的对象,并且能够停止或者转发到这个对象上的事件。它通过eventFilter()函数来接收事件,如果这个事件应该被过滤掉(如停止这个事件,或者这个事件已经被处理了,下面不再需要了),那么eventFilter函数返回true,如果不应该被过滤掉,就返回false。

QObject还提供了event filter的安装和卸载方法,如下所示:

a) QObject::installEventFilter(const QObject* filterObject)

b) QObject::removeEventFilter(QObject* filterObject)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP