最近要搞一个qt软键盘的程序,可是对qt了解的太少了。
第一部分
在qt4帮助文档中"Qt for Embedded Linux Architecture"中这样说:
每一个qt的嵌入式应用都需要有一个服务器应用程序,任何一个qt应用程序都可以作为一个服务器应用程序
当有多个qt应用程序同时运行时,子应用程序必须作为服务器程序的客户端程序。
服务器程序和客户端程序有不同的职责:服务器程序负责指针管理,字符输入,屏幕输出,还有鼠标位置和屏
幕保护。客户端执行特殊的应用。
每一个qt服务器程序的应用都是QWSserver的实例,而每个qt客户端程序又是QWSclient的实例。服务器端和客户端都
有不同的类完成不同的操作。
我的应用程序应该只有一个,就是一个单纯的服务器应用程序了。
第二部分
参考网上资料,认识下qt事件
总体轮廓:
- main(int, char **)
- QApplication::exec()
- QCoreApplication::exec()
- QEventLoop::exec(ProcessEventsFlags )
- QEventLoop::processEvents(ProcessEventsFlags )
- QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags)
Qt进入QApplication的event loop,经过层层委任,最终QEventloop的processEvent将通过与平台相关的QAbstractEventDispatcher
的子类QEventDispatcherWin32获得用户的用户输入事件,并将其打包成message后,通过标准Windows API ,把消息传递给了
Windows OS,Windows OS得到通知后回调QtWndProc, 至此事件的分发与处理完成了一半的路程。
(http://www.51cto.com/php/viewart.php?artID=272812)
- QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam) bool QETWidget::translateMouseEvent(const MSG &msg)
- bool QApplicationPrivate::sendMouseEvent(...)
- inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
- bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
- bool QApplication::notify(QObject *receiver, QEvent *e)
- bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
- bool QWidget::event(QEvent *event)
在QtWndProc中,各层函数会按照上面的顺序进驻函数堆栈。
总体来讲就是在app.exec()中会进入事件循环处理中,它会调用平台相关的系统函数得到事件,再调用notify(),或者其内部调用的函数notify_helper
event来执行相应的事件处理。
第三部分
深入qt事件,参考网络。
Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发.。
1.事件起源:基于事件如何被产生与分发,可以把事件分为以下三类。
Spontaneous 事件——自发事件
由窗口系统产生,它们被放到系统队列中,通过事件循环逐个处理。
Posted 事件
由Qt或是应用程序产生,它们被Qt组成队列,再通过事件循环处理。
Sent 事件
由Qt或是应用程序产生,但它们被直接发送到目标对象。
2.事件处理
当我们在main()函数的末尾调用QApplication::exec()时,程序进入了Qt的事件循环
首先,事件循环处理所有的posted事件,直到队列空。然后再处理所有的spontaneous事件,最后它处理所有的
因为处理spontaneous事件而产生的posted事件。
3.事件派发处理
首先说明Qt中事件过滤器的概念. 事件过滤器是Qt中一个独特的事件处理机制, 功能强大而且使用起来灵活方
便. 通过它, 可以让一个对象侦听拦截另外一个对象的事件. 事件过滤器是这样实现的: 在所有Qt对象的基类:
QObject中有一个类型为QObjectList的成员变量,名字为eventFilters,当某个QObjec (qobjA)给另一个QObject
(qobjB)安装了事件过滤器之后, qobjB会把qobjA的指针保存在eventFilters中. 在qobjB处理事件之前,会先去
检查eventFilters列表, 如果非空, 就先调用列表中对象的eventFilter()函数. 一个对象可以给多个对象安装
过滤器. 同样, 一个对象能同时被安装多个过滤器, 在事件到达之后, 这些过滤器以安装次序的反序被调用.
事件过滤器函数( eventFilter() ) 返回值是bool型, 如果返回true, 则表示该事件已经被处理完毕, Qt将直
接返回, 进行下一事件的处理; 如果返回false, 事件将接着被送往剩下的事件过滤器或是目标对象进行处理.
Qt中,事件的派发是从 QApplication::notify() 开始的, 因为QAppliction也是继承自QObject, 所以先检查
QAppliation对象, 如果有事件过滤器安装在qApp上, 先调用这些事件过滤器. 接下来QApplication::notify()
会过滤或合并一些事件(比如失效widget的鼠标事件会被过滤掉, 而同一区域重复的绘图事件会被合并). 之后,
事件被送到reciver::event() 处理.
同样, 在reciver::event()中, 先检查有无事件过滤器安装在reciever上. 若有, 则调用之. 接下来,根据
QEvent的类型, 调用相应的特定事件处理函数. 一些常见的事件都有特定事件处理函数, 比
如:mousePressEvent(), focusOutEvent(), resizeEvent(), paintEvent(), resizeEvent()等等. 在实际应
用中, 经常需要重载这些特定事件处理函数在处理事件. 但对于那些不常见的事件, 是没有相对应的特定事件
处理函数的. 如果要处理这些事件, 就需要使用别的办法, 比如重载event() 函数, 或是安装事件过滤器.
Qt中的事件可以在五个不同的层次上被处理
1.重新实现一个特定的事件handler
QObject与QWidget提供了许多特定的事件handlers,分别对应于不同的事件类型。(如
paintEvent()对应paint事件)
2.重新实现QObject::event()
event()函数是所有对象事件的入口,QObject和QWidget中缺省的实现是简单地把事件推
入特定的事件handlers。
3.在QObject安装上事件过滤器
事件过滤器是一个对象,它接收别的对象的事件,在这些事件到达指定目标之间。
4.在aApp上安装一个事件过滤器
它会监视程序中发送到所有对象的所有事件。
5.重新实现QApplication:notify()
Qt的事件循环与sendEvent()调用这个函数来分发事件,通过重写它,你可以在别人之前
看到事件。
4.事件转发
对于某些类别的事件, 如果在整个事件的派发过程结束后还没有被处理, 那么这个事件将会向上转发给它的父widget,
直到最顶层窗口. 如图所示, 事件最先发送给QCheckBox, 如果QCheckBox没有处理, 那么由QGroupBox接着处理,
如果QGroupBox没有处理, 再送到QDialog, 因为QDialog已经是最顶层widget, 所以如果QDialog不处理, QEvent将停止转发.
如何判断一个事件是否被处理了呢? Qt中和事件相关的函数通过两种方式相互通信. QApplication::notify(),
QObject::eventFilter(), QObject::event() 通过返回bool值来表示是否已处理. “真”表示已经处理, “假”表示事件需要继续传递.
另一种是调用QEvent::ignore() 或 QEvent::accept() 对事件进行标识. 这种方式只用于event() 函数和特定事件处理函数之间
的沟通. 而且只有用在某些类别事件上是有意义的, 这些事件就是上面提到的那些会被转发的事件, 包括: 鼠标, 滚轮, 按键等事件
事件的传播(propogation)
如果事件在目标对象上得不到处理,事件向上一层进行传播,直到最顶层的widget为止。
如果得到事件的对象,调用了accept(),则事件停止继续传播;如果调用了ignore(),事件向上一级继续传播。
Qt对自定义事件处理函数的默认返回值是accept(),但默认的事件处理函数是ingore()。因此,如果要继续向上传播,
调用QWidget的默认处理函数即可。到时为止的话,不必显式调用accept()。
但在event处理函数里,返回true表示accept,返回false表示向上级传播。
* 在closeEvent是个特殊情形,accept表示quit,ignore表示取消,所以最好在closeEvent显式调用accept和ignore。
1574

被折叠的 条评论
为什么被折叠?



