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

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

自定义控件结构

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

自定义窗口 PropagateWidget

PropagateWidget中添加一个PropagateLabel标签

PropagateWidget::PropagateWidget(QWidget *parent) :
    QWidget(parent)
{
    QVBoxLayout* verticalLayout=new QVBoxLayout(this);
    verticalLayout->setSpacing(0);
    verticalLayout->setContentsMargins(0,0,0,0);

    // 添加自定义标签PropagateLabel
    lbl=new PropagateLabel(this);
//    lbl->setText(QString::fromUtf8("Qt事件-总结"));
    lbl->setFrameShape(QFrame::Box);
    lbl->setFixedHeight(50);
    lbl->setAlignment(Qt::AlignCenter);
    lbl->setStyleSheet("background-color:blue;color:white;font-size:25px");

    verticalLayout->addWidget(lbl);
}

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

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

void PropagateLabel::mousePressEvent(QMouseEvent *ev)
{
    qDebug()<<"PropagateLabel::mousePressEvent";
}

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

在窗口PropagateWidget中重写 mousePressEvent

void PropagateWidget::mousePressEvent(QMouseEvent *event)
{
    qDebug()<<"PropagateWidget::mousePressEvent";
}

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

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

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

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

事件分发器-event

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

在自定义控件PropagateLabel中重写event

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

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

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

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

事件过滤器-eventFilter

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

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

bool PropagateWidget::eventFilter(QObject *watched, QEvent *event)
{
    if (watched==lbl && event->type()==QEvent::MouseButtonPress)
    {
        qDebug()<<"PropagateWidget::eventFilter";
    }
    return QWidget::eventFilter(watched,event);
}
在构造函数里为控件安装事件过滤器
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

(总结)事件传递流程图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值