(23):自定义事件

简介: (23):自定义事件

Qt 自定义事件很简单,同其它类库的使用很相似,都是要继承一个类进行扩展。在 Qt 中,你需要继承的类是QEvent。


继承QEvent类,最重要的是提供一个QEvent::Type类型的参数,作为自定义事件的类型值。回忆一下,这个 type 是我们在处理事件时用于识别事件类型的代号。比如在event()函数中,我们使用QEvent::type()获得这个事件类型,然后与我们定义的实际类型对比。


QEvent::Type是QEvent定义的一个枚举。因此,我们可以传递一个 int 值。但是需要注意的是,我们的自定义事件类型不能和已经存在的 type 值重复,否则会有不可预料的错误发生。因为系统会将你新增加的事件当做系统事件进行派发和调用。在 Qt 中,系统保留 0 – 999 的值,也就是说,你的事件 type 要大于 999。这种数值当然非常难记,这种数值当然非常难记,所以 Qt 定义了两个边界值:QEvent::User和QEvent::MaxUser。


我们的自定义事件的 type 应该在这两个值的范围之间。其中,QEvent::User的值是 1000,QEvent::MaxUser的值是 65535。从这里知道,我们最多可以定义 64536 个事件。通过这两个枚举值,我们可以保证我们自己的事件类型不会覆盖系统定义的事件类型。但是,这样并不能保证自定义事件相互之间不会被覆盖。为了解决这个问题,Qt 提供了一个函数:registerEventType(),用于自定义事件的注册。该函数签名如下:


static int QEvent::registerEventType ( int hint = -1 );


这个函数是 static 的,因此可以使用QEvent类直接调用。函数接受一个 int 值,其默认值是 -1;函数返回值是向系统注册的新的 Type 类型的值。如果 hint 是合法的,也就是说这个 hint 不会发生任何覆盖(系统的以及其它自定义事件的),则会直接返回这个值;否则,系统会自动分配一个合法值并返回。因此,使用这个函数即可完成 type 值的指定。这个函数是线程安全的,不必另外添加同步。



我们可以在QEvent子类中添加自己的事件所需要的数据,然后进行事件的发送。Qt 中提供了两种事件发送方式:


1、

static bool QCoreApplication::sendEvent(QObject *receiver,

                                       QEvent *event);


直接将event事件发送给receiver接受者,使用的是QCoreApplication::notify()函数。函数返回值就是事件处理函数的返回值。在事件被发送的时候,event对象并不会被销毁。通常我们会在栈上创建event对象,例如:


QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);

QApplication::sendEvent(mainWindow, &event);


2、

static void QCoreApplication::postEvent(QObject *receiver,

                                       QEvent *event);


将event事件及其接受者receiver一同追加到事件队列中,函数立即返回。


因为 post 事件队列会持有事件对象,并且在其 post 的时候将其 delete 掉,因此,我们必须在堆上创建event对象。当对象被发送之后,再试图访问event对象就会出现问题(因为 post 之后,event对象就会被 delete)。


当控制权返回到主线程循环时,保存在事件队列中的所有事件都通过notify()函数发送出去。


事件会根据 post 的顺序进行处理。如果你想要改变事件的处理顺序,可以考虑为其指定一个优先级。默认的优先级是Qt::NormalEventPriority。


这个函数是线程安全的。


Qt 还提供了一个函数:


static void QCoreApplication::sendPostedEvents(QObject *receiver,

                                              int event_type);


这个函数的作用是,将事件队列中的接受者为receiver,事件类似为 event_type 的所有事件立即发送给 receiver 进行处理。需要注意的是,来自窗口系统的事件并不由这个函数进行处理,而是processEvent()。详细信息请参考 Qt API 手册。



现在,我们已经能够自定义事件对象,已经能够将事件发送出去,还剩下最后一步:处理自定义事件。处理自定义事件,同前面我们讲解的那些处理方法没有什么区别。我们可以重写QObject::customEvent()函数,该函数接收一个QEvent对象作为参数:


void QObject::customEvent(QEvent *event);


我们可以通过转换 event 对象类型来判断不同的事件:


void CustomWidget::customEvent(QEvent *event) {
    CustomEvent *customEvent = static_cast<CustomEvent *>(event);
    // ...
}


当然,我们也可以在event()函数中直接处理:

bool CustomWidget::event(QEvent *event) {
    if (event->type() == MyCustomEventType) {
        CustomEvent *myEvent = static_cast<CustomEvent *>(event);
        // processing...
        return true;
    }
    return QWidget::event(event);
}


相关文章
|
JavaScript
62Vue - 自定义事件(使用自定义事件的表单输入组件)
62Vue - 自定义事件(使用自定义事件的表单输入组件)
44 0
|
JavaScript
39Vue - 事件处理器(事件修饰符)
39Vue - 事件处理器(事件修饰符)
43 0
|
6月前
|
JavaScript 前端开发
Vue如何监听键盘事件
Vue如何监听键盘事件
191 0
|
6月前
|
JavaScript
在Vue中,如何使用事件总线来传递数据和触发事件?
在Vue中,如何使用事件总线来传递数据和触发事件?
102 0
|
6月前
|
前端开发
React中事件的绑定
React中事件的绑定
|
6月前
|
前端开发 JavaScript UED
Vue3中的事件处理:事件绑定、事件修饰符、自定义事件
Vue3中的事件处理:事件绑定、事件修饰符、自定义事件
305 0
|
11月前
【Vue2.0】—事件处理和事件修饰符(二)
【Vue2.0】—事件处理和事件修饰符(二)
|
JavaScript API
61Vue - 自定义事件(使用 v-on 绑定自定义事件)
61Vue - 自定义事件(使用 v-on 绑定自定义事件)
35 0
|
JavaScript 前端开发
36Vue - 事件处理器(监听事件)
36Vue - 事件处理器(监听事件)
29 0
|
JavaScript 前端开发
37Vue - 事件处理器(方法事件处理器)
37Vue - 事件处理器(方法事件处理器)
37 0