Qt自定义事件与事件的发送

1、发送事件由以下两个函数完成

static void QCoreApplication::postEvent (QObject* receiver, QEvent* event,
int priority=Qt::NormalEventPriority);
static bool QCoreApplication::sendEvent(QObject* receiver, QEvent* event)

receiver:指向接收事件的对象
event:表示需要发送的事件
priority:表示事件的优先级, 事件会按优先级排序,高优先级的事件排在队列的前面。 其取值为枚举类型 Qt::EventPriority 中的枚举值。
如下
Qt::HighEventPriority:值为 1。
Qt::NormalEventPriority:值为 0。
Qt::LowEventPriority:值为-1。
优先级只是一个相对值,其值可取介于规定的最大值和最小值之间的任何值,比如可使 priority 参数的值为 Qt::HighEventPriority +10。

2、发送事件(sendEvent)与发布事件(postEvent)

①、 发送(send)事件:把事件直接发送给接收事件的目标对象。事件发送之后不会被删除,
发送的事件通常创建在堆栈上。
②、发布(post)事件:
 把事件添加到事件队列中,并立即返回。
 发布事件必须在堆(比如使用 new)上创建事件,因为事件被发布后,事件队列将
获得事件的所有权并自动将其删除。 发布事件后再访问该事件是不安全的。
 发布事件还可以对事件进行合并(或称为压缩),比如在返回事件循环之前连续发
布了多个相同的事件,则这多个相同的事件会自动合并为一个单一的事件。 可合
并的事件有鼠标移动事件、调整大小事件等。

3、自定义事件原理

①、基本原理:事件其实就是使用的一个整数值表示的,因此在创建自定义事件时,只须给事件指定一个整数值即可,在 Qt 中,这个整数值是通过枚举类型 QEvent::Type 定义的,事件的其他信息可以封装在一个自定义的类之中。
②、 自定义的事件即可以是预定义类型,也可以是自定义类型的。
③、 自定义类型的事件,需要定义一个事件编号,该编号必须大于 QEvent :: User(其值为1000),小于 QEvent::MaxUser(其值为 65535)。
④、各种事件不能重叠(即 QEvent::Type 类型的值不能相同),小于 QEvent::User 的事件是Qt 内部定义的事件,他们不会重叠,对于自定义的事件可以使用 registerEventType()函数来保证事件不重叠,
该函数原型如下:
static int QEvent::registerEventType ( int hint = -1 );
如果 hint 的值不会产生重叠,则会返回这个值;如果 hint 不合法,系统会自动分配一
个合法值并返回。因此, 可使用该函数的返回值创建 Type 类型的值。

4、 创建自定义事件的方法和步骤

①、可以使用以下方式创建自定义事件
使用 QEvent 的构造函数创建事件,其原型为:
QEvent(Type type);
示例: QEvent::Type t1=(QEvent::Type)1333; //定义事件编号
QEvent e(t); //创建事件 e
使用 Qt 已创建好的事件类型创建事件,比如使用 QKeyEvent 类创建键盘事件。
继承 QEvent 类,创建自定义事件。
②、使用 QCoreApplication::postEvent()或 QCoreApplication::sendEvent()函数发送事件。
③、可使用以下方法处理自定义事件
重写 QObject::event()函数,在该函数内直接处理自定义事件或调用自定义的事
件处理函数处理事件。
安装事件过滤器,然后在过滤器对象的 eventFilter()函数中处理自定义事件。
当然,还可以重写 QCoreApplication::notify()函数。

自定义事件demo:

#include <QApplication>
#include<QWidget>
#include<QObject>
#include <iostream>
using namespace std;
QEvent::Type t1=(QEvent::Type)1333;
QEvent e(t1); //使用 QEvent 的构造函数在堆栈上创建自定义事件
class E:public QEvent{
public: //子类化 QEvent 以创建自定义事件
    //方式 1:使用静态成员。
    //使用静态成员主要是为了正确初始化父类部分 QEvent,比如
    //E():t2((QEvent::Type)1324),QEvent(t2){}, 若 t2 不是静态的,则则初始化之后 t2 为 1324,但传递
    //给 QEvent 的 t2 是一个不确定的值,因为按照 C++规则,对父类部分的初始化先于数据成员的初始化。
    static QEvent::Type t2; //注意:不要使用名称 t,因为 QEvent 类之中有一个名称为 t 的成员变量。
    E():QEvent(t2){}
    //方式 2:使用带一个参数的构造函数
    QEvent::Type t3;
    explicit E(QEvent::Type t4):t3(t4),QEvent(t4){}
};
QEvent::Type E::t2=(QEvent::Type)1334;
class A:public QWidget{
public:
    bool event(QEvent* e)
    { //重写 event 函数以处理自定义事件
        if(e->type()==t1) //判断事件类型是否为 t1
        {
            cout<<"AE"<<e->type()<<",";
            f1((E*)e); //调用自定义的处理函数处理该事件
            return 1;
        }
        if(e->type()==E::t2)
        {
            cout<<"BE"<<e->type()<<",";
            f2((QEvent*)e); return 1;
        }
        if(e->type()==((E*)e)->t3)
        {
            cout<<"CE"<<e->type()<<",";
            f3((E*)e); return 1;
        }
        return QWidget::event(e);
    } //event 结束
    //以下为处理自定义事件的事件处理函数
    void f1(E *e)
    {
        cout<<"F1"<<endl;
    }
    void f2(QEvent *e)
    {
        cout<<"F2"<<endl;
    }
    void f3(E *e)
    {
        cout<<"F3"<<endl;
    }
}; //类 A 结束。
int main(int argc, char *argv[])
{
    QApplication aa(argc,argv);
    A ma;
    E me;
    E *pe=new E((QEvent::Type)1335);
    //发布或发送事件
    aa.sendEvent(&ma,&e);
    aa.sendEvent(&ma,&me);
    aa.postEvent(&ma,pe);
    //aa.postEvent(&ma,&me); //错误,发布的事件 me 必须是在堆上创建的。
    ma.resize(333,222);
    ma.show();
    aa.exec();
    return 0;
}

使用事件过滤器处理自定义事件demo:

#include <QApplication>
#include<QWidget>
#include<QObject>
#include <iostream>
using namespace std;
QEvent::Type t1=(QEvent::Type)QEvent::registerEventType(1333);
QEvent e1(t1); //使用 QEvent 的构造函数创建自定义事件
//t2 的值与 t1 重复,使用 registerEventType 会自动产生一个合法的值
QEvent::Type t2=(QEvent::Type)QEvent::registerEventType(1333);
QEvent e2(t2);
class A:public QWidget{
public:
bool event(QEvent* e)
{
if(e->type()==t1) 
{
cout<<"AE"<<e->type()<<",";
 f1((QEvent*)e); 
return 1; 
}
if(e->type()==t2) 
{
cout<<"BE"<<e->type()<<",";
 f2((QEvent*)e); 
return 1; 
}
return QWidget::event(e); 
} //event 结束
void f1(QEvent *e)
{
cout<<"F1"<<endl;
}
void f2(QEvent *e)
{
cout<<"F2"<<endl;
}
};
class B:public QObject{public:
bool eventFilter(QObject *w, QEvent *e)
{
if(e->type()==t1)
{ 
cout<<"A"<<endl;return 1;
}
if(e->type()==t2)
{
 cout<<"B"<<endl;return 0;
 }
return 0;
}
};
int main(int argc, char *argv[])
{
QApplication aa(argc,argv);
A ma;
B mb;
ma.installEventFilter(&mb); //安装事件过滤器
aa.sendEvent(&ma,&e1);
aa.sendEvent(&ma,&e2);
ma.resize(333,222); 
ma.show(); 
aa.exec();
return 0; 
}

本例依次输出 A B BE65535,F2, 其中 65535 为使用 registerEventType 函数为 t2 分配的合法的数值。 可见,安装事件过滤器之后,发送的事件 e1 和 e2 会使用过滤器对象的eventFilter 函数进行处理。

5、事件的传递顺序总结

event()函数、事件过滤器、和事件处理函数的调用顺序如下:
首先按逆序调用事件过滤器(同一对象安装多个事件过滤器),然后调用 event()函数,最后调用事件处理函数(注意:事件处理函数需在 event()函数中明确或间接调用,否则不会调用事件处理函数)。
 

猜你喜欢

转载自blog.csdn.net/weixin_41882459/article/details/113049604