什么是事件??
事件是各种应用程序需要知道的有有应用程序内部或者外部产生的事情或者动作的通称。
在Qt中使用 一个对象来表示一个事件,继承自QEvent类。常见的有键盘事件QKeyEvent、鼠标事件QMouseEvent、定时器事件QTimerEvent。任何QObject子类都可以接受和处理事件。
事件和信号的区别?
二者并不相同;比如单击一下界面上的按钮,那么就会产生鼠标事件(不是按钮产生的),但是因为俺就被按下了,所以他会发射clicked()单击信号 (是按钮产生的)。事件和按钮是不同层面的东西。
----------------------事件的处理----------------------
一个事件由一个特定的QEvent子类来表示,但是又是一个事件又包含很多类型,比如鼠标事件由可以分为:鼠标按下,双击,移动等,这些事件类型由QEvent类中的枚举类型QEvent::Type来表示,其中包含了100多种事件类型。
五种事件的处理方法:
- 重新实现部件的paintEvent()、mousePressvent()等事件处理函数。这也是最常用的方法。
- 重新实现notify()函数,可以在事件过滤器得到事件之前就获得他们,但是一次只能处理一个事件,
- 向QApplication()对象上安装事件过滤器, 功能与使用和notify()函数相同,但是同时处理多个事件。
- 重新实现event()函数;(QObject: :event()函数 可以在事件到达事件处理函数之前获得该事件。)
- 在对象上安装事件过滤器。(可以在一个界面类中同时处理不同子部件的不同事件)
(实际编程中最常用的方式是1,其次是5) 。
举个栗子::
在主窗口widget中加入一个lineEdit,在lineEdit中一输入就出发键盘事件:
mylineedit.h文件
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H
#include <QLineEdit>
#include <QKeyEvent>
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
MyLineEdit(QWidget* parent = 0);
protected:
void keyPressEvent(QKeyEvent* event);//添加事件函数
};
#endif // MYLINEEDIT_H
mylineedit.cpp文件
#include "mylineedit.h"
#include <QDebug>
#include <QEvent>
MyLineEdit::MyLineEdit(QWidget *parent)
:QLineEdit(parent)
{
}
void MyLineEdit::keyPressEvent(QKeyEvent *event)
{
qDebug()<<tr("MyLineEdit键盘按下事件");
QLineEdit::keyPressEvent(event); //执行QLineEdit类中的默认事件处理
event->ignore //忽略该事件
}
Widget.h文件
#ifndef WIDGET_H
#define WIDGET_H
#include "mylineedit.h"
#include <QWidget>
class MyLineEdit;//前置声明
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected:
void keyPressEvent(QKeyEvent *event);//Widget中的事件函数
private:
Ui::Widget *ui;
MyLineEdit* line;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "mylineedit.h"
#include <QDebug>
#include <QEvent>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
line = new MyLineEdit(this);
line->move(100,100);
}
Widget::~Widget()
{
delete ui;
}
void Widget::keyPressEvent(QKeyEvent *event)
{
qDebug()<<tr("Widget键盘按下事件");
}
运行结果:
我们看到:我们自定义了一个MyLineEdit类,他继承QLineEdit类,然后在Widget界面中添加了一个MylineEdit部件。这里都实现了MyLineEdit类和Widget类的键盘按下时事件处理函数。运行程序,当我们按下键盘,发现目前只执行了MyLineEdit类的keyPressEvent()函数。
下面我们在mylineedit.h文件中的keyPressEvent()函数后面添加一行代码:
event->ignore(); //忽略该事件。
此时运行程序:
按下键盘,发现输出多了“Widget键盘按下事件”;说明执行了Widget类中的keyPressEvent()函数。
但是目前行编辑仍然不能输入,我们在MyLineEdit类中keyPressEvent()函数中添加如下代码(注意:要在event->ignore();前添加):
QLineEdit::keyPressEvent(event);
此时运行程序,我们发现行编辑中可以输入了。
总结:
从这个例子中我们可以发现,事件先是传递给指定的窗口部件的,(获得窗口的焦点部件。),如果该部件忽略掉这个事件,那么这个事件就会传递给这个部件的福部件,重新实现事件处理函数时,一般要调用父类的相应事件处理函数来实现默认操作。
下面使用事件过滤器等方法获取事件的顺序:
在上面的代码做出如下更改:
在mylineedit.h文件中添加event函数声明:
bool event(QEvent *event);
在mylineedit.cpp中对该函数定义:
bool MyLineEdit::event(QEvent *event)
{
//如果是Event中的键盘事件,就执行QLineEdit类的event()函数的默认操作。
if(event->type() == QEvent::KeyPress)
qDebug()<<tr("MyLineEdit的event()函数");
return QLineEdit::event(event);
}
event()的作用:
事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。event()函数主要用于事件的分发。
接着在Widget.h文件中对事件过滤器进行声明:、
bool eventFilter(QObject *obj, QEvent *event);//声明事件过滤器
在Widget.cpp文件中添加事件过滤器的定义:
bool Widget::eventFilter(QObject *obj, QEvent *event)//事件过滤器的定义
{
if(obj == line) //如果是lineEdit部件上的事件
{
if(event->type() == QEvent::KeyPress)//r=如果事件类型是键盘事件
qDebug()<<tr("Widget的事件过滤器");
}
return QWidget::eventFilter(obj,event); //返回了QWidget类默认的事件过滤器的执行结果
}
运行程序:
可以看出事件的传递顺序是:
事件过滤器---->焦点部件的event函数----->焦点部件事件处理函数;如果焦点部件忽略了该事件,那么会执行父部件的事件处理函数。