Qt 事件传递流程-事件处理器|事件分发器|事件过滤器

(总体传递流程图见文章末尾)

自定义控件结构

 

自定义继承于QLabel的控件类 PropagateLabel.h

 

自定义窗口 PropagateWidget

 

PropagateWidget中添加一个PropagateLabel标签

 1 PropagateWidget::PropagateWidget(QWidget *parent) :
 2     QWidget(parent)
 3 {
 4     QVBoxLayout* verticalLayout=new QVBoxLayout(this);
 5     verticalLayout->setSpacing(0);
 6     verticalLayout->setContentsMargins(0,0,0,0);
 7 
 8     // 添加自定义标签PropagateLabel
 9     lbl=new PropagateLabel(this);
10 //    lbl->setText(QString::fromUtf8("Qt事件-总结"));
11     lbl->setFrameShape(QFrame::Box);
12     lbl->setFixedHeight(50);
13     lbl->setAlignment(Qt::AlignCenter);
14     lbl->setStyleSheet("background-color:blue;color:white;font-size:25px");
15 
16     verticalLayout->addWidget(lbl);
17 }

 

事件处理器-指定控件的指定事件

在自定义控件PropagateLabel中重写鼠标点击事件 mousePressEvent

1 void PropagateLabel::mousePressEvent(QMouseEvent *ev)
2 {
3     qDebug()<<"PropagateLabel::mousePressEvent";
4 }

 

鼠标点击控件,检测到事件输出相应信息

 

在窗口PropagateWidget中重写 mousePressEvent

1 void PropagateWidget::mousePressEvent(QMouseEvent *event)
2 {
3     qDebug()<<"PropagateWidget::mousePressEvent";
4 }

如果窗口检测到鼠标点击事件将会有相应输出

 

在自定义控件中设置事件接收状态为accept,则控件检测到事件之后不会传递给父控件(PropagateWidget),此时点击标签只有自定义控件的输出,即父控件检测不到事件

 

在自定义控件中设置事件接收状态为ignore,则控件检测到事件之后会传递给父控件(PropagateWidget),由输出可以看出,自定义控件先检测事件,然后传递给父控件,此时父控件能检测到事件

 

如果没有显式指定事件接收状态,则默认为accep,即省略ev->accept/ev->ignore,默认父控件检测不到事件

 

事件分发器-event

事件分发器在事件处理器之前获取事件

 

在自定义控件PropagateLabel中重写event

1 bool PropagateLabel::event(QEvent *e)
2 {
3     if (e->type()==QEvent::MouseButtonPress) // 指定需要检测的事件
4     {
5         qDebug()<<"PropagateLabel::event";
6     }
7     return QLabel::event(e); // 返回 把事件传递下去
8 }

 

由输出顺序可知,event先检测到事件,然后传递给默认事件处理器

 

如果在if分支中return true,则只有event能检测到事件

 

如果return false,则事件不会再被控件的默认事件处理器检测到,直接传递给父控件

 

事件过滤器-eventFilter

在事件到达控件之前拦截事件

 

在窗口PropagateWidget中重写事件过滤器

1 bool PropagateWidget::eventFilter(QObject *watched, QEvent *event)
2 {
3     if (watched==lbl && event->type()==QEvent::MouseButtonPress)
4     {
5         qDebug()<<"PropagateWidget::eventFilter";
6     }
7     return QWidget::eventFilter(watched,event);
8 }

 

在构造函数里为控件安装事件过滤器

lbl->installEventFilter(this);

 

输出顺序可以看到事件过滤器最早获取事件

 

最后一句 QWidget::eventFilter ,Qt里的定义为直接return false,即最后一句等价于直接写return false,事件会继续传递下去

在if分支里return true,则事件过滤器会拦截事件,不再传递下去

 

事件过滤器原理上是阻止某个控件截取事件,而不是令某个控件对事件做出反应

例如,控件A中有一个子控件B,我们希望控件A对事件X做出反应,但是在运行过程中发现事件X会被控件B截取,导致控件A获取不到事件,这时就可以给控件B安装事件过滤器,在事件X到达控件B之前截取,然后越过控件B传递给控件A

(总结)事件传递流程图

 

posted @ 2024-08-28 15:25  SAKURA12  阅读(33)  评论(0编辑  收藏  举报