最近项目中碰到了如标题的实际需要,网上相关资料较少。大部分都是子窗口安装父窗口的过滤器,然后子窗口的事件会被送到父窗口的eventFilter()函数来进行处理。
如果是父窗口安装子窗口。就起实际意义来讲,确实实用性不大。比如一个点击事件,子窗口置顶显示时的事件交互,会优先与子窗口进行事件交互,甚至是子窗口完全将此次事件截取。从而使得父窗口在此几何区域内不会收到此次事件。
一般情况下用不到父窗口安装子窗口的事件过滤器,但是除非特殊的任务需求。
需要子窗口中重新实现事件过滤器函数eventFilter()
定义两个窗口部件 父Widget 类 和 子 SubWidget类
1.SubWidget子部件头文件
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
#include <QLabel>
#include <QEvent>
class SubWidget : public QLabel
{
public:
SubWidget(QWidget* parent);
bool eventFilter(QObject* obj,QEvent *ev) override;
void mousePressEvent(QMouseEvent *ev)override;
};
#endif // SUBWIDGET_H
2.SubWidget子部件.CPP
#include "subwidget.h"
SubWidget::SubWidget(QWidget *parent)
: QLabel(parent)
{
this->setStyleSheet("background-color : rgb(150,0,0);");
this->setGeometry(0,0,300,300);
this->move(200,200);
this->show();
}
bool SubWidget::eventFilter(QObject* obj,QEvent *ev)
{
if(ev->type()==QEvent::MouseButtonPress){
if(obj == this->parent()){
qDebug()<<"子部件拦截了父部件事件,鼠标按在了父窗口上!";
return false;//事件透传,会将此鼠标事件继续传递下去。
}
else{
qDebug()<<"子部件拦截了父部件事件,鼠标没有按在父窗口上!";
return true;//设置真,确认了事件已经被处理.不会继续透传
}
}
return QLabel::eventFilter(obj,ev);
}
void SubWidget::mousePressEvent(QMouseEvent *ev)
{
qDebug()<<"已执行子窗口的鼠标事件处理函数";
}
3.Widget父部件头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "dialog.h"
#include "subwidget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
SubWidget* subwidget;
void mousePressEvent(QMouseEvent* ev) override;
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
4.Widget父部件.CPP
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QkeyEvent>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->subwidget = new SubWidget(this);//指定子部件
this->installEventFilter(this->subwidget);//父窗口安装子窗口的事件过滤器
}
Widget::~Widget()
{
delete ui;
}
void Widget::mousePressEvent(QMouseEvent *ev)
{
qDebug()<<"已执行父窗口的鼠标事件处理函数";
}
运行效果如下
1.鼠标点击绿色部分(1),有以下输出
没有执行父部件安装的子部件的过滤器函数,说明父部件没有收到鼠标事件。显然,子部件图层是在父部件的上方,因此事件分发只会到达子部件。
2.鼠标点击白色部分(2),有以下输出
父部件安装的子部件的过滤器函数和父部件本身的事件处理函数都执行了。但是过滤器的优先级更高,优先执行其子部件的事件过滤器处理函数。但是由于我们在过滤器函数内部设立了一个return false;没有将此事件标记为处理完成。因此这个鼠标事件会继续透传,所以父部件后续才会收到这个事件来执行自己的鼠标事件处理函数。
欢迎指正与讨论!