事件分发函数 event()
事件分发器:返回值 bool
如果返回时true,代表用户要处理事件,不再分发事件了。
- 事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。
- event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理(eventhandler)。
因此如上所述,event()函数主要用于事件的分发。所以,如果你希望在事件分发之前做一些操作,就可以重写这个event()函数了。
event事件
#include <QEvent>
- 用途:用于事件的分发
- 也可以用作拦截事件(不建议)
例如,我们希望在一个QWidget组件中监听 tab 键的按下,那么就可以继承QWidget,并重写它的event()函数,来达到这个目的
//事件分发器
bool mylabel::event(QEvent *e)
{
if(e->type() == QEvent::KeyPress)
{
静态类型转换
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(e);
if(keyEvent->key()==Qt::Key_Tab)
{
qDebug()<<"tab had pressed";
return true;
}
}
return QWidget::event(e);
}
做一个拦截的目的时,说明它可以做拦截。
实际应用就是鼠标事件就用鼠标相应的函数操作,定时器就用定时器。
//事件分发器
bool mylabel::event(QEvent *e)
{
//如果键盘按下,在event事件分发中做拦截操作
if(e->type() == QEvent::MouseButtonPress)
{
//静态类型转换
QMouseEvent *ev = static_cast<QMouseEvent*>(e);
QString str = QString("Event函数中,鼠标按下了 x = %1,y=%2 globalX =%3 globalY = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
}
}
//会做类型检查,相对安全,但是带来的成本高于static_cast
QMouseEvent *ev = dynamic_cast<QMouseEvent*>(e);//会做类型检查,相对安全,但是带来的成本高于static_cast
事件过滤器(了解即可)
- 事件过滤器可以对需要的组件接收到的事件进行过滤,以及监控
- 任意的QObject对象都可以作为事件过滤器使用
- 事件过滤器的实现,需要重写eventFilter()函数
- 组件要想被监控,则需要通过installEventFilter()安装事件过滤器
- 事件过滤器能够决定是否将事件转发给组件对象,如下图所示:
obj->installEventFilter(filterObject);常常是obj->installEventFilter(this).
- 发送到obj的所有事件, 都会先发送到filterObject的eventFilter()方法,
- 即filterObject会过滤obj的事件, 这样就不用为了实现一个事件而要去继承, 再实现一个类, 完成如mouse event, key event等了, 只用在当前类中就可以通过事件过滤来完成.
在程序将事件分发到事件分发器前,可以利用过滤器拦截
1.给控件安装事件过滤器
2.重写eventFilter函数(obj,sv)
public:
explicit Event(QWidget *parent = nullptr);
~Event();
//重写事件过滤器事件
bool eventFilter(QObject*obj,QEvent*e);
#include "event.h"
#include "ui_event.h"
#include <QDebug>
#include <QMouseEvent>
#include <QEvent>
Event::Event(QWidget *parent) :
QWidget(parent),
ui(new Ui::Event)
{
ui->setupUi(this);
//步骤一安装事件过滤器
ui->label->installEventFilter(this);
//步骤2L重写eventfilter事件
}
bool Event::eventFilter(QObject*obj,QEvent*e)
{
if(obj == ui->label)
{
if(e->type() == QEvent::MouseButtonPress)
{
//静态类型转换
QMouseEvent *ev = dynamic_cast<QMouseEvent*>(e);//会做类型检查,相对安全,但是带来的成本高于static_cast
//QMouseEvent *ev = static_cast<QMouseEvent*>(e);
QString str = QString("EventFilter函数中,鼠标按下了 x = %1,y=%2 globalX =%3 globalY = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
}
}
//其他默认处理
return QWidget::eventFilter(obj,e);
}
Event::~Event()
{
delete ui;
}
Qt事件处理介绍
- Qt平台会将系统产生的消息转换为Qt事件
- Qt事件是一个QEvent的对象
- Qt事件用来描述程序内部或外部发生的动作
- 任意的QObject对象都具备事件处理的能力
如下图所示,可以看到QEvent的子类非常之多:
- **QInputEvent:**用户输入事件
- **QDropEvent:**用户拖放事件
- **QPaintEvent:**描述操作系统绘制GUI动作的事件
- **QCloseEvent:**用户关闭窗口事件
- **QTimerEvent:**计时器事件
事件处理方式顺序
1.Qt事件产生后立即被分发到QWidget对象
2.QWidget中的**event(QEvent*)**进行事件处理
3.event()根据事件类型调用不同的事件处理函数
4.在事件处理函数中发送Qt中预定义的信号
5.调用信号关联的槽函数
举个例子:
1.当点击按钮后,将会触发**鼠标事件,调用event(QEvent*)**成员函数
3.调用**mouseReleaseEvent(QMouseEvent*)**成员函数
4.调用**click()**成员函数
5.触发信号SIGNAL(clicked());
同样,当用户点击窗口的关闭按钮时,也会触发closeEvent()事件函数,该函数需要重写,才能实现
void MainWindow::closeEvent(QCloseEvent *event)
{
if (maybeSave()) //如果还有需要保存的数据
{
writeSettings();
event->accept();
}
else //取消关闭窗口
{
event->ignore();
}
}
类似的还有**keyEvent()**获取键盘事件函数, **keyReleaseEvent()**键盘按下事件函数,enterEvent光标进入组件事件函数, leaveEvent光标离开组件事件函数等等。
其中QCloseEvent继承与QEvent,在QEvent中常用成员函数有
void accept (); //接收者处理当前事件
void ignore (); //接收者忽略当前事件,忽略后,事件可能传递给父组件
bool isAccepted(); //判断当前事件是否被