前言
QML两个MouseArea重叠在一起导致下方的MouseArea无法获取到鼠标点击事件
解决方案
当mouseArea与其它mouseArea项目重叠时,可以设置propagateComposedEvents属性为true来传播clicked,doubleClicked和pressedAndHold等事件。但是只有在mouseArea没有接受这些事件的时候,它们才可以继续向下传播。也就是说,当事件已经在一个mouseArea中进行处理,则需要在其事件处理器中设置MouseEvent.acceptd为false,这样该事件才能继续传播。
import QtQuick 2.9
import QtQuick.Window 2.3
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
Window {
id:mainWindow
property int count: 0
visible: true
width: 400
height: 400
title: qsTr("Hello World")
Rectangle{
id:rect_1
width: 100
height: 100
color: "cyan"
MouseArea{
anchors.fill: parent
onClicked: {
console.log("点击了青色的矩形");
}
}
}
Rectangle{
id:rect_2
x:50
y:50
width: 100
height: 100
color: "red"
MouseArea{
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
console.log("点击了红色的矩形");
mouse.accepted = false;
}
}
}
}
思考
在QML中处理较为简单,下面介绍如何在Widget中处理这种情况
有一个自定义的widget
重写了void mousePressEvent(QMouseEvent *event)
。当鼠标在上面点击时会打印出鼠标的位置。如果在上面在添加一个QPushButton
发现如果点击在按钮上面只会执行按钮点击相关的函数。解决方案是自定义一个Button
在处理点击事件时新建一个事件发送到父对象的widget
中。
MyWidget.cpp
#include "MyWidget.h"
#include "ui_MyWidget.h"
#include <QDebug>
#include <QMouseEvent>
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyWidget)
{
ui->setupUi(this);
//设置此属性,qss设置widget背景才能生效
this->setAttribute(Qt::WA_StyledBackground);
}
MyWidget::~MyWidget()
{
delete ui;
}
void MyWidget::mousePressEvent(QMouseEvent *event)
{
qDebug() << QStringLiteral("点击了 x : %1; y : %2").arg(event->x()).arg(event->y());
}
MyWidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = nullptr);
~MyWidget();
protected:
void mousePressEvent(QMouseEvent *event) override;
private:
Ui::MyWidget *ui;
};
#endif // MYWIDGET_H
MyPushButton.cpp
#include "MyPushButton.h"
#include <QMouseEvent>
#include <QPointF>
#include <QCoreApplication>
MyPushButton::MyPushButton(QWidget *parent) : QPushButton(parent)
{
}
void MyPushButton::mousePressEvent(QMouseEvent *event)
{
if(this->parentWidget())
{
//将Button点击的坐标转换为父Widget的坐标后然后新建一个事件发送给父Widget
QPointF point = mapTo(this->parentWidget(), event->pos());
//注意这里的 new 不会造成内存泄漏,详见QT帮助文档 postEvent 的解释
QMouseEvent *event_ = new QMouseEvent(event->type(), point, event->button(), event->buttons(), event->modifiers());
QCoreApplication::postEvent(this->parentWidget(), event_);
}
QPushButton::mousePressEvent(event);
}
MyPushButton.h
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H
#include <QWidget>
#include <QPushButton>
class MyPushButton : public QPushButton
{
Q_OBJECT
public:
explicit MyPushButton(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *event) override;
signals:
public slots:
};
#endif // MYPUSHBUTTON_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->widget->setStyleSheet("#widget{\
background-color:pink\
}");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
qDebug() << QStringLiteral("按钮被点击了");
}
效果
最后可以发现点击按钮的同时,自定义的widget
的mousePress
函数也能够正确打印