![](http://blog.51cto.com/image/skin/artType01.jpg)
![](https://i-blog.csdnimg.cn/blog_migrate/603adcd85ef19e7cbd537579dfdc3a3f.png)
原创作品,允许转载,转载时请务必以超链接形式标明文章
原始出处 、作者信息和本声明。否则将追究法律责任。
http://devbean.blog.51cto.com/448512/232314
这部分将作为Qt事件部分的结束。我们在前面已经从大概上了解了Qt的事件机制。下面要说的是如何自定义事件。
Qt允许你创建自己的事件类型,这在多线程的程序中尤其有用,当然,也可以用在单线程的程序中,作为一种对象间通讯的机制。那么,为什么我需要使用事件,而不是使用信号槽呢?主要原因是,事件的分发既可以是同步的,又可以是异步的,而函数的调用或者说是槽的回调总是同步的。事件的另外一个好处是,它可以使用过滤器。
Qt中的自定义事件很简单,同其他类似的库的使用很相似,都是要继承一个类进行扩展。在Qt中,你需要继承的类是QEvent。 注意,在Qt3中,你需要继承的类是QCustomEvent,不过这个类在Qt4中已经被废除(这里的废除是不建议使用,并不是从类库中删除)。
继承QEvent类,你需要提供一个QEvent::Type类型的参数,作为自定义事件的类型值。这里的QEvent::Type类型是QEvent里面定义的一个enum,因此,你是可以传递一个int的。重要的是,你的事件类型不能和已经存在的type值重复,否则会有不可预料的错误发生!因为系统会将你的事件当做系统事件进行派发和调用。在Qt中,系统将保留0 - 999的值,也就是说,你的事件type要大于999. 具体来说,你的自定义事件的type要在QEvent::User和QEvent::MaxUser的范围之间。其中,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中提供了两种发送方式:
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);
}
这两种办法都是可行的。
好了,至此,我们已经概略的介绍了Qt的事件机制,包括事件的派发、自定义等一系列的问题。下面的章节将继续我们的学习之路!
Qt允许你创建自己的事件类型,这在多线程的程序中尤其有用,当然,也可以用在单线程的程序中,作为一种对象间通讯的机制。那么,为什么我需要使用事件,而不是使用信号槽呢?主要原因是,事件的分发既可以是同步的,又可以是异步的,而函数的调用或者说是槽的回调总是同步的。事件的另外一个好处是,它可以使用过滤器。
Qt中的自定义事件很简单,同其他类似的库的使用很相似,都是要继承一个类进行扩展。在Qt中,你需要继承的类是QEvent。 注意,在Qt3中,你需要继承的类是QCustomEvent,不过这个类在Qt4中已经被废除(这里的废除是不建议使用,并不是从类库中删除)。
继承QEvent类,你需要提供一个QEvent::Type类型的参数,作为自定义事件的类型值。这里的QEvent::Type类型是QEvent里面定义的一个enum,因此,你是可以传递一个int的。重要的是,你的事件类型不能和已经存在的type值重复,否则会有不可预料的错误发生!因为系统会将你的事件当做系统事件进行派发和调用。在Qt中,系统将保留0 - 999的值,也就是说,你的事件type要大于999. 具体来说,你的自定义事件的type要在QEvent::User和QEvent::MaxUser的范围之间。其中,QEvent::User值是1000,QEvent::MaxUser的值是65535。从这里知道,你最多可以定义64536个事件,相信这个数字已经足够大了!但是,即便如此,也只能保证用户自定义事件不能覆盖系统事件,并不能保证自定义事件之间不会被覆盖。为了解决这个问题,Qt提供了一个函数:registerEventType(),用于自定义事件的注册。该函数签名如下:
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
函数是static的,因此可以使用QEvent类直接调用。函数接受一个int值,其默认值为-1,返回值是创建的这个Type类型的值。如果hint是合法的,不会发生任何覆盖,则会返回这个值;如果hint不合法,系统会自动分配一个合法值并返回。因此,使用这个函数即可完成type值的指定。这个函数是线程安全的,因此不必另外添加同步。
你可以在QEvent子类中添加自己的事件所需要的数据,然后进行事件的发送。Qt中提供了两种发送方式:
- static bool QCoreApplication::sendEvent(QObjecy * receiver, QEvent * event):事件被QCoreApplication的notify()函数直接发送给receiver对象,返回值是事件处理函数的返回值。使用这个函数必须要在栈上创建对象,例如:
QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
QApplication::sendEvent(mainWindow, & event);
- static bool QCoreApplication::postEvent(QObject * receiver, QEvent * event):事件被QCoreApplication追加到事件列表的最后,并等待处理,该函数将事件追加后会立即返回,并且注意,该函数是线程安全的。另外一点是,使用这个函数必须要在堆上创建对象,例如:
QApplication::postEvent( object, new MyEvent(QEvent::registerEventType(2048)));
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
另外,你也可以通过重写event()函数来处理自定义事件:
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
return QWidget:: event( event);
![](https://i-blog.csdnimg.cn/blog_migrate/78e1e3a115342bc8b092d7d92afd6281.png)
这两种办法都是可行的。
好了,至此,我们已经概略的介绍了Qt的事件机制,包括事件的派发、自定义等一系列的问题。下面的章节将继续我们的学习之路!
本文出自 “豆子空间” 博客,请务必保留此出处http://devbean.blog.51cto.com/448512/232314