QT学习之事件处理

  • Qt事件机制

    Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发.。

    Qt事件的发生和处理成为程序运行的主线,存在于程序整个生命周期。

    Qt事件的类型很多, 常见的qt的事件如下:

    键盘事件: 按键按下和松开.

    鼠标事件: 鼠标移动,鼠标按键的按下和松开.

    拖放事件: 用鼠标进行拖放.

    滚轮事件: 鼠标滚轮滚动.

    绘屏事件: 重绘屏幕的某些部分.

    定时事件: 定时器到时.

    焦点事件: 键盘焦点移动.

    进入和离开事件: 鼠标移入widget之内,或是移出.

    移动事件: widget的位置改变.

    大小改变事件: widget的大小改变.

    显示和隐藏事件: widget显示和隐藏.

    窗口事件: 窗口是否为当前窗口.

     

    还有一些非常见的qt事件,比如socket事件,剪贴板事件,字体改变,布局改变等等.

     

    交流会围绕以下三个问题展开:

    一、什么是事件?

    二、事件是怎样被处理的?

    三、事件与信号的区别?

     

    一、什么是事件?

    事件:某个“动作”的完成后,需让某个对象知道而发送的消息。(个人观点)

    解释:此时的“动作”并非通常意义所指的动作,而是广义的“动作”,是主动和被动的总和。

    例:两个窗体A和B,当A为最小化状态时,我们使它最大化,这就会让A主动产生一个重绘事件;当A和B非最小化状态,且B位于A窗体之上时,我们让B最小化,那么刚才被B遮挡的A窗体就会被动地产生一个重绘事件。

    Qt 的事件和Qt中的signal不一样. 后者通常用来"使用"widget, 而前者用来"实现" widget. 比如一个按钮, 我们使用这个按钮的时候, 我们只关心他clicked()的signal, 至于这个按钮如何接收处理鼠标事件,再发射这个信号,我们是不用关心的. 但是如果我们要重载一个按钮的时候,我们就要面对event了. 比如我们可以改变它的行为,在鼠标按键按下的时候(mouse press event) 就触发clicked()的signal而不是通常在释放的( mouse release event)时候.

    我们按产生来源把事件分为两类:

    (一) 系统产生的;通常是window system把从系统得到的消息,比如鼠标按键,键盘按键等, 放入系统的消息队列中,Qt事件循环的时候读取这些事件,转化为QEvent,再依次处理.

    (二)是由Qt应用程序程序自身产生的.程序产生事件有两种方式, 一种是调用QApplication::postEvent(). 例如QWidget::update()函数,当需要重新绘制屏幕时,程序调用update()函数,new出来一个paintEvent,调用 QApplication::postEvent(),将其放入Qt的消息队列中,等待依次被处理. 另一种方式是调用sendEvent()函数. 这时候事件不会放入队列, 而是直接被派发和处理, QWidget::repaint()函数用的就是这种方式。

    二、事件是怎样被处理的?

    (一)两种调度方式,一种是同步的, 一种是异步.

     

    Qt的事件循环是异步的,当调用QApplication::exec()时,就进入了事件循环. 该循环可以简化的描述为如下的代码:

     

    while ( !app_exit_loop )

    {

       while( !postedEvents ) { processPostedEvents() }

       while( !qwsEvnts ){ qwsProcessEvents();   }

       while( !postedEvents ) { processPostedEvents() }

     

    }

     

    先处理Qt事件队列中的事件, 直至为空. 再处理系统消息队列中的消息, 直至为空, 在处理系统消息的时候会产生新的Qt事件, 需要对其再次进行处理.

     

    调用QApplication::sendEvent的时候, 消息会立即被处理,是同步的. 实际上QApplication::sendEvent()是通过调用QApplication::notify(), 直接进入了事件的派发和处理环节.

     

    (二) 事件的派发和处理

    首先说明Qt中事件过滤器的概念. 事件过滤器是Qt中一个独特的事件处理机制, 功能强大而且使用起来灵活方便. 通过它, 可以让一个对象侦听拦截另外一个对象的事件. 事件过滤器是这样实现的: 在所有Qt对象的基类: QObject中有一个类型为QObjectList的成员变量,名字为eventFilters,当某个QObjec (qobjA)给另一个QObject (qobjB)安装了事件过滤器之后, qobjB会把qobjA的指针保存在eventFilters中. 在qobjB处理事件之前,会先去检查eventFilters列表, 如果非空, 就先调用列表中对象的eventFilter()函数. 一个对象可以给多个对象安装过滤器. 同样, 一个对象能同时被安装多个过滤器, 在事件到达之后, 这些过滤器以安装次序的反序被调用. 事件过滤器函数( eventFilter() ) 返回值是bool型, 如果返回true, 则表示该事件已经被处理完毕, Qt将直接返回, 进行下一事件的处理; 如果返回false, 事件将接着被送往剩下的事件过滤器或是目标对象进行处理.

     事件过滤器的代码实现:
    这个代码实现了点击图片进行放大的功能(属于事件过滤器的操作实例)

    #ifndef EVENTFILTER_H
    #define EVENTFILTER_H
    
    #include <QDialog>
    #include <QLabel>
    #include <QImage>
    #include <QEvent>
    
    class EventFilter : public QDialog
    {
        Q_OBJECT
        
    public:
        EventFilter(QWidget *parent = 0,Qt::WindowFlags f=0);
        ~EventFilter();
    public slots:
        bool eventFilter(QObject *, QEvent 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值