发送QT中的预定义事件

我们知道,用户的操作会被操作系统感知到,然后操作系统会将用户的操作翻译成系统消息,然后这个系统消息经过一系列变化就会变成QT事件对象,那么这样的事件是由操作系统发送过来的。

事件对象的由来不仅仅是由操作系统带来的,我们也可以在程序中自主的发送事件对象,可以发送QT中预定义的事件对象,也可以发送QT中自定义的事件对象。

在一般的GUI开发平台中,存在两种事件发送方式,一种是阻塞型事件发送,另外一种是非阻塞型事件发送。

-阻塞型事件发送:事件发送后需要等待事件处理完成

-非阻塞型事件发送:事件发送后立即返回,事件被发送到事件队列中等待处理。

在QT开发平台下,对这2种事件的表现形式为:

                   

sendEvent(QObject* receiver,QEvent* event) 中事件对象的生命期由QT程序管理,它同时支持栈事件对象和堆事件对象的发送

postEvent(QObject* receiver,QEvent* event) 中事件对象的生命期由Qt平台管理,它只能发送堆事件对象,事件被处理后由Qt平台销毁。

来看一下 sendEvent(QObject* receiver,QEvent* event) 为什么是阻塞型的?

                         

因为在sendEvent(QObject* receiver,QEvent* event)函数内部,直接调用了Qt对象的event()事件处理函数,当event()事件处理函数没有返回时,sendEvent(QObject* receiver,QEvent*  event)就肯定不会返回,所以sendEvent()是阻塞型的。

                            

而在postEvent(QObject* receiver,QEvent* event)函数内部,是直接将事件发送到事件队列中去等待处理,然后事件被发送到事件队列中去之后,它就马上返回了,然后事件队列里面的事件就会被分发下去,分发到具体的对应QT对象上去,然后具体的QT对象就会调用自己的event()事件处理函数进行事件处理,所以它不是阻塞型的。

 

下面用一个程序实例来验证上面的原理。

#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui/QWidget>
#include <QPushButton>

class Widget : public QWidget
{
    Q_OBJECT
private:
    QPushButton m_pushButton;

protected slots:
    void onButtonClicked();
public:
    Widget(QWidget *parent = 0);

    void testSendEvent();
    void testPostEvent();

    bool event(QEvent* evt);

    ~Widget();
};

#endif // WIDGET_H
#include "Widget.h"
#include <QMouseEvent>
#include <QApplication>
#include <QDebug>

Widget::Widget(QWidget *parent): QWidget(parent)
{
    m_pushButton.setParent(this);
    m_pushButton.setText("TestButton");


    connect(&m_pushButton,SIGNAL(clicked()),this,SLOT(onButtonClicked()));
}

void Widget::onButtonClicked()
{
     testSendEvent();
    //testPostEvent();
}

void Widget::testSendEvent()
{
    QMouseEvent dbcEvt(QEvent::MouseButtonDblClick,QPoint(0,0),Qt::LeftButton,Qt::NoButton,Qt::NoModifier);

    qDebug()<<"Before() sendEvent()";

    QApplication::sendEvent(this,&dbcEvt);//将一个鼠标的双击事件发送到当前的Widget对象上来

    qDebug()<<"After sendEvent()";
}

void Widget::testPostEvent()
{
    QMouseEvent* dbcEvt=new QMouseEvent(QEvent::MouseButtonDblClick,QPoint(0,0),Qt::LeftButton,Qt::NoButton,Qt::NoModifier);

    qDebug()<<"Before() postEvent()";

    QApplication::postEvent(this,dbcEvt);//将一个鼠标的双击事件发送到当前的Widget对象上来

    qDebug()<<"After postEvent()";
}

bool Widget::event(QEvent* evt)
{
    if(evt->type()==QEvent::MouseButtonDblClick)
    {
        qDebug()<<"event():"<<evt;
    }

    return QWidget::event(evt);
}

Widget::~Widget()
{
    
}
#include <QtGui/QApplication>
#include "Widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    
    return a.exec();
}

分析上述程序:

                         

                         

因为sendEvent是阻塞型的,所以在打印出Before() sendEvent()之后,会去调用event()事件处理函数,等event()函数处理完成之后,才会打印After sendEvent()。

接下来看postEvent()的非阻塞型。

                  

因为postEvent是非阻塞型的,然后它发送的事件会将它发送到事件队列中去,然后最后事件队列中的事件将会把他们分发给对应的QT对象进行处理,所以打印的结果才会最后调用bool event(QEvent* evt)这个函数。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

repinkply

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值