Event事件机制

1.事件类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

QAbstractEventDispatcher //Interface to manage Qt's event queue
QBasicTimer //Timer events for objects
QChildEvent //Contains event parameters for child object events
QDynamicPropertyChangeEvent //Contains event parameters for dynamic property change events
QEvent //The base class of all event classes. Event objects contain event parameters
QTimerEvent //Contains parameters that describe a timer event
QTimer //Repetitive and single-shot timers
QActionEvent //Event that is generated when a QAction is added, removed, or changed
QCloseEvent //Contains parameters that describe a close event
QContextMenuEvent //Contains parameters that describe a context menu event
QDragEnterEvent //Event which is sent to a widget when a drag and drop action enters it
QDragLeaveEvent //Event that is sent to a widget when a drag and drop action leaves it
QDragMoveEvent //Event which is sent while a drag and drop action is in progress
QDropEvent //Event which is sent when a drag and drop action is completed
QEnterEvent //Contains parameters that describe an enter event
QExposeEvent //Contains event parameters for expose events
QFileOpenEvent //Event that will be sent when there is a request to open a file or a URL
QFocusEvent //Contains event parameters for widget focus events
QHelpEvent //Event that is used to request helpful information about a particular point in a widget
QHideEvent //Event which is sent after a widget is hidden
QHoverEvent //Contains parameters that describe a mouse event
QIconDragEvent //Indicates that a main icon drag has begun
QInputEvent //The base class for events that describe user input
QInputMethodEvent //Parameters for input method events
QKeyEvent //Describes a key event
QMouseEvent //Contains parameters that describe a mouse event
QMoveEvent //Contains event parameters for move events
QNativeGestureEvent //Contains parameters that describe a gesture event
QPaintEvent //Contains event parameters for paint events
QPlatformSurfaceEvent //Used to notify about native platform surface events
QPointingDeviceUniqueId //Identifies a unique object, such as a tagged token or stylus, which is used with a pointing device
QResizeEvent //Contains event parameters for resize events
QScrollEvent //Sent when scrolling
QScrollPrepareEvent //Sent in preparation of scrolling
QShortcutEvent //Event which is generated when the user presses a key combination
QShowEvent //Event that is sent when a widget is shown
QStatusTipEvent //Event that is used to show messages in a status bar
QTabletEvent //Contains parameters that describe a Tablet event
QTouchEvent //Contains parameters that describe a touch event
QWhatsThisClickedEvent //Event that can be used to handle hyperlinks in a "What's This?" text
QWheelEvent //Contains parameters that describe a wheel event
QWindowStateChangeEvent //The window state before a window state change
QGestureEvent //The description of triggered gestures
QShortcut //Used to create keyboard shortcuts

2.事件函数

今天要说的是event()函数。记得之前曾经提到过这个函数,说在事件对象创建完毕后,Qt将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。

event()函数主要用于事件的分发,所以,如果你希望在事件分发之前做一些操作,那么,就需要注意这个event()函数了。为了达到这种目的,我们可以重写event()函数。例如,如果你希望在窗口中的tab键按下时将焦点移动到下一组件,而不是让具有焦点的组件处理,那么你就可以继承QWidget,并重写它的event()函数,已达到这个目的:

1
2
3
4
5
6
7
8
9
bool MyWidget::event(QEvent *event) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Tab) {
// 处理Tab鍵
return true;
}
}
return QWidget::event(event);

3.事件过滤机制

Qt创建了QEvent事件对象之后,会调用QObject的event()函数做事件的分发。有时候,你可能需要在调用event()函数之前做一些另外的操作,比如,对话框上某些组件可能并不需要响应回车按下的事件,此时,你就需要重新定义组件的event()函数。如果组件很多,就需要重写很多次event()函数,这显然没有效率。为此,你可以使用一个事件过滤器,来判断是否需要调用event()函数。

QOjbect有一个eventFilter()函数,用于建立事件过滤器。这个函数的签名如下:

1
virtual bool QObject::eventFilter(QObject *obj, QEvent *event);

如果obj对象安装了事件过滤器,这个函数会被调用并进行事件过滤,然后才轮到组件进行事件处理。在重写这个函数时,如果你需要过滤掉某个事件,例如停止对这个事件的响应,需要返回true。

上面的例子中为MainWindow建立了一个事件过滤器。为了过滤某个组件上的事件,首先需要判断这个对象是哪个组件,然后判断这个事件的类型。例如,我不想让textEdit组件处理键盘事件,于是就首先找到这个组件,如果这个事件是键盘事件,则直接返回true,也就是过滤掉了这个事件,其他事件还是要继续处理,所以返回false。对于其他组件,我们并不保证是不是还有过滤器,于是最保险的办法是调用父类的函数。

在创建了过滤器之后,下面要做的是安装这个过滤器。安装过滤器需要调用installEventFilter()函数。这个函数的签名如下:

1
void QObject::installEventFilter(QObject *obj);

这个函数是QObject的一个函数,因此可以安装到任何QObject的子类,并不仅仅是UI组件。这个函数接收一个QObject对象,调用了这个函数安装事件过滤器的组件会调用filterObj定义的eventFilter()函数。例如,textField.installEventFilter(obj),则如果有事件发送到textField组件是,会先调用obj->eventFilter()函数,然后才会调用textField.event()。

当然,你也可以把事件过滤器安装到QApplication上面,这样就可以过滤所有的事件,已获得更大的控制权。不过,这样做的后果就是会降低事件分发的效率。

如果一个组件安装了多个过滤器,则最后一个安装的会最先调用,类似于堆栈的行为。