Qt分析-事件机制与延伸

mac2024-07-26  16

Qt事件机制

【引自博主-unclerunning】https://blog.csdn.net/unclerunning/article/details/70226794#qt

事件过滤器

概述

Qt事件过滤器详解

过滤器与父类

eventFilter是虚函数,因此在#派生类木有过滤器函数(超类有)的情况下,可直接安装派生类中UI之具体控件到超类的过滤器。即(举例):

//超类 bool WidgetSuper::eventFilter(QObject *pObject, QEvent *pEvent) { //..Special Deal Event Code //comm return QWidget::eventFilter(pObject, pEvent); } //派生类 Form_1::Form_1(QWidget *parent) : WidgetSuper(parent), ui(new Ui::Form_1) { ui->setupUi(this); ui->pushButton->installEventFilter(this); } //bool Form_1::eventFilter(QObject *pObject, QEvent *pEvent) //{ //..Special Deal Event Code //personal //return WidgetSuper::eventFilter(pObject, pEvent); //}

一旦派生类自身也重写eventFilter函数,若此时还想使用超类过滤器中的事件处理,则必须在派生类的eventFilter函数最后,调用其父类同名函数。事件会向父窗口传递,但是不会自动向父类传递。

过滤器与父窗口

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); //设置焦点样式表 this->setStyleSheet("QLabel:focus{background-color:yellow;}\ QLineEdit:focus{background-color:yellow;}\ QPushButton:focus{background-color:yellow;}"); //方案1 //ui->stackedWidget->installEventFilter(this); //方案2 this->installEventFilter(this); } bool Widget::eventFilter(QObject *pObject, QEvent *pEvent) { if (QEvent::KeyPress == pEvent->type()) { QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent); switch (pKeyEvent->key()) { case Qt::Key_A: qDebug() << "Qt::Key_A"; break; //..... } } return QWidget::eventFilter(pObject, pEvent); }

//代码注释 场景: PushButton-1是ui->stackedWidget#Widget_Page1的一个StrongFocus的控件,click或Tab或setFocus将窗口焦点设置在PushButton-1上,然后按下Key_A键盘,希望在ui对应类的过滤器函数中能捕获到这一事件! //方案1 //ui->stackedWidget->installEventFilter(this);

//方案2 this->installEventFilter(this); 因为QPushButton本身不会对Key_A有任何的处理,故此事件会向其父窗口传递,若还不处理,继而向祖父窗口传递。在各级父对象中,若有安装过滤器的,则执行他们的过滤器函数,若都没有则该事件将被系统做默认处理。

控件的焦点属性,对键盘事件的捕获起作用(键盘事件首先有系统分配到焦点控件)。

某控件安装多个过滤器

给QObject对象安装事件过滤器:对象用installEventFilter()后,所有达到目标控件的事件都首先到达监视对象的eventFilter()函数。如果一个对象有多个事件过滤器,过滤器按顺序激活,先到达最近安装的监视对象,最后到达最先安装的监视对象。

过滤鼠标事件

写过滤器时,可以插一嘴,QWidget::grabMouse 试试父窗口强占的鼠标事件在其EventFilter中分发给其子控件后,会不会再次被他抢来,从而进入无限循环。 测试结果,到是没有无限循环,但是确实又被捕获了。对于那些可以直接调用执行(不必事件转发)的情况,这种方案勉强可以使用。

使用过滤器改变窗口或控件的原始响应,如,按键响应、鼠标响应等–可以展开

//核心:转换rect为全局区域 //translated

QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(pEvent); //目标区域左上角->转全局坐标 QPoint posOffset = m_pRecvWdt->mapToGlobal(QPoint(0, 0)); //目标矩形(TP:0-0)->全局区域 QRect rectGlobal = m_pRecvWdt->rect()->translated(posOffset); //判断鼠标位置在关注范围内 return rectGlobal.contains(mouseEvent->globalPos()) ? true, false;

源码解析

【引自博主-lfsblackoverflow】 https://www.cnblogs.com/lfsblack/p/5279143.html

事件循环

模态与非模态情况下的事件循环-

事件发送

有个问题,对于new的自定义事件,postEvent后,要不要我们自己去delete呢?[答案只能去源码中寻找la]

先来看一篇:Qt中postEvent和sendEvent函数 https://blog.csdn.net/xiaoyink/article/details/79404377

走,去看源码喽,直接顺着postEvent的源码一路F2向下查,不难发现,步步return前都会存在delete过程。再看这个函数的注释:The event must be allocated on the heap since the post event queue will take ownership of the event and delete it once it has been posted. It is {not safe} to access the event after it has been posted. When control returns to main event loop, all events that are stored in the queue will be sent using the notify() function.

最新回复(0)