在QT中,事件是一个继承QEvent的对象。事件通过调用QObject::event()方法被分发到继承自QObject的对象。事件分发意味着事件已经发生了,QEvent精确的指出QObject需要作何反应。大多数的事件被指定到QWidge及他的子类,但是也有很重要的事件不依赖于图形而发生,例如,socket激活,事件被QSocketNotifier利用进行工作。
一些事件来自视窗系统,例如:QMouseEvent,一些来自其他源,例如:QTimerEvent,还有一些来自于应用程序。通常Qt是对称的,所以你可以发送事件用相同的方法向QT自己的事件循环那样。
大多数的事件类型有指定的类,最常用的,QResizeEvent,QPaintEvent,QMouseEvent,QKeyEvent和QCloseEvent.也有其他的,大约有四十个左右,但是都很少用到。
每一个类子类QEvent并且增加指定事件的函数;注意啦,例如,QResizeEvent。在QResizeEvent的情况下,QResizeEvent:size()和QResizeEvent:oldSize()被添加。
一些类支持超过一种事件类型。QMouseEvent支持鼠标move,presses,shift-presses,drags,clicks,right-presses等等
因为程序需要反应于多变的和复杂的方式,Qt的事件分发技术是灵活的。QApplication::notify()的文档简明的描述了这整个过程,这里我们将充分的解释99%的应用。
一个事件被分发的通常的方法是通过调用一个虚函数。例如,QPaintEvent通过调用QWidget::paintEvent()被分发。这个虚函数负责正确的响应,重新绘画这个widget.
有时候不存在那样的一个特定的事件函数,或者特定的那个函数不能充分的满足需求。最通常的例子是tab键的press动作,它通常被QWidget认为是移动键盘的焦点,但是一些widgets本身需要TAB键。
这些对象能重新实现QObject::event(),通常的事件处理方法,在通常的处理事件的前后做他们的事件处理,或者完全代替它。一个非常不寻常的widget既解释tab又有一个指定应用的自定义事件可能包含:
更一般的,一个对象需要监视另外的事件。Qt支持它通过QObject::installEventFilter()(和相应的去除动作)。例如,对话框对于一些widget想过滤掉按键操作,举个例子,改变回车键处理。
事件过滤器开始处理事件在目标对象行动之前。过滤器的QObject::eventFilter()实现被调用,能接受或者丢弃过滤,允许或者拒绝事件的更进一步的处理。如果所有的事件过滤器允许更进一步的事件处理,事件将被发送到目标对象本身。如果他们中的一个停止处理,目标和任何后来的事件过滤器不能看到任何事件。
可以过滤整个应用的所有的事件,通过在QApplication中安装一个事件过滤器。QToolTip就是通过这种办法看到键盘和鼠标的所有活动。非常强大,但是这也降低了在整个应用中每个单一事件的分发速度,所以还是最好避免。
指定对象的过滤器被调用之前全局事件过滤器会被首先调用。
最后,许多应用想要生成和发送他们自己的事件。
生成一个内建类型的事件是非常简单的:生成相应类型的一个对象,然后调用QApplication::sendEvent()或者QApplication::postEvent()。
sendEvent()立刻处理事件--当sendEvent()返回的时候,(事件过滤器和)对象已经处理完了事件。对于许多的事件类有一个函数叫做isAccepted()将被调用告诉你是否事件已经被接受或被最后一个处理者丢弃
postEvent()投送事件到一个队列以备之后分发。下一次Qt的主事件循环运行的时候,分发所有的已经投送的事件,附带一些优化,比如,如果有几次resize事件将被紧缩成一个。对于相同的应用paint事件:QWidget::update()调用postEvent(),通过避免多次repaint减少闪烁加快速度。
postEvent()也经常用在对象初始化,因此已经投送的事件将不久被分发在对象初始化完成之后。
对于生成自定义类型的事件,你需要定义一个事件号,它必须要大于QEvent::User,为了传递你自定义事件的特征你可能需要子类QCustomEvent
详细的请看QCustomEvent的文档
原文出处: