qt事件相关学习笔记

最近要搞一个qt软键盘的程序,可是对qt了解的太少了。

 

第一部分

在qt4帮助文档中"Qt for Embedded Linux Architecture"中这样说:

    每一个qt的嵌入式应用都需要有一个服务器应用程序,任何一个qt应用程序都可以作为一个服务器应用程序

当有多个qt应用程序同时运行时,子应用程序必须作为服务器程序的客户端程序。

服务器程序和客户端程序有不同的职责:服务器程序负责指针管理,字符输入,屏幕输出,还有鼠标位置和屏

幕保护。客户端执行特殊的应用。

每一个qt服务器程序的应用都是QWSserver的实例,而每个qt客户端程序又是QWSclient的实例。服务器端和客户端都

有不同的类完成不同的操作。

 

我的应用程序应该只有一个,就是一个单纯的服务器应用程序了。

 

第二部分

参考网上资料,认识下qt事件

总体轮廓:

  1. main(int, char **)   
  2. QApplication::exec()   
  3. QCoreApplication::exec()   
  4. QEventLoop::exec(ProcessEventsFlags )   
  5. QEventLoop::processEvents(ProcessEventsFlags )   
  6. 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

 

  1. QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, 

               LPARAM lParam) bool QETWidget::translateMouseEvent(const MSG &msg)   

  1. bool QApplicationPrivate::sendMouseEvent(...)   
  2. inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)   
  3. bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)   
  4. bool QApplication::notify(QObject *receiver, QEvent *e)   
  5. bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)   
  6. 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。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值