图形界面的终端事件传送机制的参考资料

 简介: 事件是由窗口系统或 Qt 本身对各种事务的反应而产生的。 当用户按下一个键或者鼠标按钮,就会相应产生一个键盘或者鼠标事件。 当窗口第一次显示,会产生一个绘图事件,从而通知最新的可见窗口绘制自身。 使用 Qt 编程时,很少需要考虑事件,因为 Qt 的窗口组件会在事件发生的时候发送信号,然后利用 Signal-Slot 机制进行相应的事件处理。 但是,在编写自定义 Widget 或者需要修改现有Widget的特性时,或者需要处理平台相关的底层事件时,事件则变得很重要。 本文以 XWindow 平台为例,介绍 Qt 如何处理平台相关的底层事件。

1. Qt 中与平台相关的宏定义

Qt 提供了以下标识系统的宏定义,如表1所示:


表 1. Qt 提供的系统标识宏定义
系统标志 对应的平台
Q_WS_WIN Windows
Q_WS_X11 XWindow
Q_WS_MAC Mac

如果项目中调用了平台相关的 APIs ,那么利用条件编译,使得源程序不用修改,就可以适用于不同的平台。

对于 XWindow 平台,代码片断如清单1所示:


清单 1. 
                        
#if defined(Q_WS_X11)
//与 XWindow 相关的 native APIs
#endif
      

对于 Windows 平台,代码片断如清单2所示:


清单 2. 
                        
#if defined(Q_WS_WIN)
//与 Windows 相关的 native APIs 
#endif
      

对于 MAC 平台,代码片断如清单3所示:


清单 3. 
                        
#if defined(Q_WS_MAC)
//与Mac相关的native APIs
#endif
      

2. Xlib 与 XEvent

Xlib 是 XWindow 提供的 API 集合,Xlib 之上是 Xt Intrinsics library,Xt 采用面向对象的设计方法,提供了大量的 widgets。 在 Xt 之上则是各种各样的 toolkits,最常用的是 Motif。 Qt 没有对 Xt 进行封装,而是直接建立在 Xlib 之上。

Xlib 用一个叫"XEvent"的结构来保存从 X 服务器那里接收到的事件。 Xlib 提供了大量的事件类型。 XEvent 包括事件的类型,以及与事件相关的数据。

Qt 也定义了一组事件类。 其中 QEvent 是基类。 其他具体事件类,例如 QMouseEvent、QKeyEvent、QFocusEvent、QPaintEvent、QMoveEvent、QResizeEvent 等都是从 QEvent 继承而来。 多数情况下,利用 Qt 的事件机制,能够满足我们的需求。 但是,在某些特定的情况,我们需要能够截获 XWindow 的底层事件,并对其进行处理。 本文介绍了两种截获 XEvent 的方法,一种是重载 QApplication 的 x11EventFilter() 方法;另一种是重载 QWidget 的 x11Event() 方法。 文中提供的例子基于 Qt 4.3,并在 Fedora Core 6 上调试通过。

3. QApplication::x11EventFilter() 如何工作

QApplication 类管理 Qt 应用程序的控制流和主要设置。 它包含了主事件循环,对来自窗口系统的所有事件进行处理和调度。 它也处理应用程序的初始化和结束,并且提供对话管理。

QApplication 中定义了针对 XWindow 平台的虚函数,如清单4所示:


清单 4. 
                        
bool QApplication::x11EventFilter ( XEvent * )
      

创建 QApplication 的子类,并且重新实现函数 x11EventFilter(),那么所有底层的 XEvent 会首先被函数 x11EventFilter() 截获。 如果希望在函数 x11EventFilter() 中针对某事件进行响应,那么在响应结束后返回 TRUE,表示该事件不会被分派到 QApplication 的 Qt 主事件循环中。 如果函数返回 FALSE,那么该事件会被继续分派到 QApplication 的 Qt 主事件循环中,由 Qt 包装成 Qt 事件。

此外,针对 Windows 平台,QApplication 定义了类似的虚函数,如清单5所示:


清单 5. 
                        
bool QCoreApplication::winEventFilter ( MSG * msg, long * result )
      

针对 Mac 平台,QApplication 定义了类似的虚函数,如清单6所示:


清单 6. 
                        
bool QApplication::macEventFilter ( EventHandlerCallRef caller, EventRef event )
      

下面通过一个例子说明,如何在 Qt 中处理 XEvent。 该例子包括两个可执行程序,一个是 xclient,另一个是 qtx11filter。 xclient 基于 Xlib,向 qtx11filter 发送 XClientMessageEvent。 qtx11filter 截获所有的 XEvent,但只对 XClientMessageEvent 进行处理,将其它所有类型的 XEvent 都分派到 QApplication 的 Qt 主事件循环中。

你可能感兴趣的:(操作系统,图形)