最近学习了Qt学习之路中的事件,对此进行各总结和测试,做一个对事件的基本认识。
事件与信号槽区别,信号槽是同步的,而事件可以同步和异步的,如sendEvent直接发给接受者,postEvent投递到事件队列队尾,前面处理完了再处理。
信号是由具体对象发出,直接调用接收者的对应slot函数,而事件时有Qt统一管理的。
Qt的事件大体分为以下层次:
1.QCoreApplication::notify()
2.QApplicationm::eventFilter()
3.QApplication::event()
4.组件的eventFilter()
5.组件的event()
6.组件的一些现有事件函数如keyPressEvent等
1.事件过滤器
virtual boolQObject::eventFilter( QObject *watched, QEvent *event )
重写过滤器,对事件进行过滤。
若对事件过滤则return true反之return false
同时还得对事件过滤器安装
void QObject::installEventFilter( QObject * filterObj)
注意,如果你在事件过滤器中 delete 了某个接收组件, 务必将返回值设为 true。否则,Qt 还是会将事件分发给这个接收组件,从而导致程序崩溃。
事件过滤器和被安装的组件必须在同一线程, 否则,过滤器不起作用。另外,如果在install 之后,这两个组件到了不同的线程,那么,只有等到二者重新回到同一线程的时候
过滤器才会有效。
2.事件分发函数
event() 函数主要用于事件的分发,所以,如果你希望在事件分发之前做一些操作,那么,就需要注意这个 event()函数了。 为了达到这种目的,我们可以重写 event()函数。
bool QObject::event(QEvent *event)
return true 告知QCoreApplication::notfiy()已经处理事件
return QWidget::event(event) 由父类继续事件处理
3.自定义事件
Qt 中的自定义事件,需要继承 的类是 QEvent。
继承 QEvent 类,你需要提供一个 QEvent::Type 类型的参数,作为自定义事件的类型值
你的自定义事件的 type 要 在QEvent::User 和 QEvent::MaxUser 的 范 围 之 间 。 其 中 , QEvent::User 值 是 1000,QEvent::MaxUser 的值是 65535。 从这里知道,你最多可以定义 64536 个事件。
static int QEvent::registerEventType ( int hint = -1 );
函数是 static 的,因 此可以使用 QEvent 类直接调用。函数接受一个 int 值,其默认值为-1,返回值是创建的这个 Type 类型的值。如果 hint 是合法的,不会发生任何覆 盖,则会返回这个值;如果 hint 不合法,系统会自动分配一个合法值并返回。 因此,使用这个函数即可完成 type 值的指定。这个函数是线程安全的,因此不 必另外添加同步。
static bool QCoreApplication::sendEvent(QObjecy * receiver, QEvent *event)
事件被 QCoreApplication 的 notify()函数直接发送给 receiver 对象,返回值是事件处理函数的返回值。使用这个 函数必须要在栈上创建对象
static bool QCoreApplication::postEvent(QObject * receiver, QEvent *event)
事件被 QCoreApplication 追加到事件列表的最后,并等待处理,该函数将事件追加后会立即返回,并且注意,该函数是线程安全的。 另外一点是,使用这个函数必须要在堆
上创建对象
这个对象不需要手动 delete,Qt 会自 动 delete 掉!因此,如果在 post 事件之后调用delete,程序可能会崩溃
如果要处理自定义事件, 可以重写 QObject 的 customEvent()函数或者在event()函数中处理。
下面是整个一起的代码,比较偷懒。
#ifndef MYEVENT_H
#define MYEVENT_H
#include <QString>
#include <QEvent>
class MyEvent : public QEvent
{
public:
MyEvent(Type type,const QString &msg);
QString getMsg();
bool setMsg(QString &msg);
private:
QString _msg;
};
#endif // MYEVENT_H
#include "myevent.h"
MyEvent::MyEvent(Type type,const QString &msg):
QEvent(type)
{
_msg = msg;
}
QString MyEvent::getMsg()
{
return _msg;
}
bool MyEvent::setMsg(QString &msg)
{
_msg = msg;
return true;
}
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
installEventFilter(this);
evenType = QEvent::registerEventType(QEvent::User+1);
}
Widget::~Widget()
{
delete ui;
}
bool Widget::eventFilter( QObject * watched, QEvent * event)
{
if(watched == this){
if(event->type() == QEvent::KeyPress){
qDebug()<<"key press(eventFilter)\n";
}
}
return false;
}
bool Widget::event(QEvent * e)
{
if(e->type() == QEvent::KeyPress){
qDebug()<<"key press(event)\n";
keyPressEvent((QKeyEvent *)e);
return true;
}
return QWidget::event(e);
}
void Widget::keyPressEvent(QKeyEvent * event)
{
if(event->type() == QEvent::KeyPress){
qDebug()<<"key press(keyPressEvent)\n";
QApplication::postEvent(this,new MyEvent((QEvent::Type)evenType,tr("hello event")));
}
}
void Widget::customEvent (QEvent * event)
{
if(event->type() == evenType){
MyEvent *e = static_cast<MyEvent *>(event);
qDebug()<<"custom envent\n";
qDebug()<<e->getMsg();
}
}
对于Qt的事件到此,也算是基本了解。