事件Event:
事件是由窗口系统和Qt自身产生的,用以响应发生的各类事情,例如用户按下键盘或者鼠标,都会产生一个键盘或鼠标的事件。大多数事件是用于的动作相应的,小数是由系统独立产生的,如定时器事件。要记住“事件”和“信号”是两种不同的概念。
重载键盘事件函数:
如果我们想自定义事件处理函数,只需要重载相关的事件函数就行了,如我需要对点击“F3”按键的事件进行处理,代码如下:
//重载keyPressEvent()
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_F3)
{
//todu
}
//把事件传递给父窗口部件来处理
QWidget::keyPressEvent(event);
}
定时器事件:
调用startTimer()后会分配一个唯一的标识号,每隔一段时间都会调用一次timerEvent()
//在mainwindow.h中
void timerEvent(QTimerEvent *event);
int myTimerId;
//在mainwindow.cpp中
//开启定时器
myTimerId = startTimer(500);
void MainWindow::timerEvent(QTimerEvent *event)
{
if(myTimerId == event->timerId())
{
//todo
}
}
//关闭定时器
killTimer(myTimerId);
myTimerId = 0;
补充:
定时器还可以这样用QTimer::singleShot(0, this, SLOT(function()));功能是马上触发定时器执行槽函数,这种用法多用于构造函数中耗时较长的初始功能,为了避免因为耗时的原因界面没有加载出来,使用户认为是应用程序启动失败。
定时器事件是一种低级事件,当需要多个定时器时,一个定时器对应一个ID这会让追踪定时器变得困难,因此最好的方法是创建QTimer对象。
事件过滤器:
假设现在有一个需求,界面上有四个QLineEdit,点击QlineEdit后光标在上面显示,当我们输入空格键时光标调到下一个QLineEdit上。
我们可以子类化QLineEdit,用上面重载键盘事件函数的方法实现,但当是不同的窗口部件(QSpinBox,QComboBox等)之间实现这个需求时,子类化每个窗口部件类是非常麻烦的,所以我们可以用事件过滤器实现。
Qt事件模型的一个非常强大的功能是QObject实例(例如窗口部件)在看到它自己的事件之前,可以通过设置另一个QObject实例先监视这些事件。我的理解是父窗体可以先监视子窗口的事件,并在监视代码中实现相应功能。
使用过滤器的步骤为:
1、目标对象(窗口部件)调用installEventFilter()注册监视对象
2、在监视对象的eventFilter()中处理目标对象(窗口部件)的事件。
过滤器代码实例:
//在mainwindow.h中
QLineEdit *lineEdit1;
QLineEdit *lineEdit2;
void eventFilter(QObject *target, QEvent *event);
//在mainwindow.cpp中
//构造函数中
{
...
lineEdit1 = new QLineEdit(this);
lineEdit2 = new QLineEdit(this);
lineEdit1->installEventFilter(this);
lineEdit2->installEventFilter(this);
...
}
//重载eventFilter()
bool MainWindow::eventFilter(QObject *target, QEvent *event)
{
//检查目标对象
if(target == lineEdit1 || target == lineEdit2)
{
//判断是否键盘按下事件
if(event->type() == QEvent::KeyPress)
{
//将事件强制转换为键盘事件,为了可以调用keyEvent->key()
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); //判断是否空格键
if(keyEvent->key() == Qt::Key_Space)
{
//todo
return true;
}
}
}
//如果目标对象不对,不是按键按下事件,就调用基类的eventFilter,因为基类eventFilter也可能正在监控某个窗口部件。
return QWidget::eventFilter(target,event);
}
Qt提供五个级别的事件处理和时间过滤方法(序号越大级别越高):
1、重新实现特殊的事件处理器
即重载按键按下,鼠标单击等事件处理函数
2、重新实现QObject:event()
通过event()函数的重新实现,可以让事件到达特定的事件处理器前处理它们。
3、在Object中安装事件过滤器
4、在QApplicantion对象中安装事件过滤器
应用程序的每个对象都会在事件发送到其他事件过滤器之前,先发送给这个eventFilter()函数。
5、子类化QApplicantion并且重载notify()
QApplicatn::processEvent():
当调用QApplicant:exec()时,就启动了Qt的事件循环。当处理一个事件时(执行功能函数),也有可能有产生别的事件并会添加到事件队列中。当处理这个事件耗时太长时,其他事件无法进行,用户界面就无法响应了,如无法进行鼠标点击,这时解决的方法有两种:
1、利用多线程方法,将处理应用程序的用户界面和耗时的操作分开为不同的线程
2、频繁调用QApplicatn::processEvent(),这个函数的作用是告诉Qt处理那些还没被处理的事件,这可以让用户界面继续操作,因此QApplicant:exec()就是一个不断调用QApplicatn::processEvent()的while循环。