QT事件透明度仅适用于部分小部件

时间:2015-04-30 12:32:47

标签: c++ qt events widget

软件显示3个小部件:

  • 主窗口
  • 内容小部件,涵盖了大部分主窗口
  • 自定义小部件,涵盖主窗口和内容小部件的一部分。

自定义窗口小部件的一部分(定义为QRect)需要Event-opaque,而周围区域必须为Event-transparent

我尝试过:

setAttribute(Qt::WA_TransparentForMouseEvents);

但是,自定义的所有子窗口小部件也变得透明。

我也尝试使用setMask,但随后自定义小部件无法在周围区域进行绘制。

如何实现这种部分事件透明度?

示例(它没有解释完整的问题,只需添加一个测试解决方案的基础):

main.cpp

#include "transparentwidget.hpp"
#include "normalwidget.hpp"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // Main Window
    NormalWidget window;
    window.resize(500,500);
    window.setObjectName("window");
    window.setStyleSheet("background-color: rgba(0,0,128,128); ");

    // Content window
    NormalWidget content(&window);
    content.setObjectName("content");
    content.resize(400, 400);
    content.move(0,0);
    content.setStyleSheet("background-color: rgba(128,0,0,128);");

    TransparentWidget custom(&window);
    custom.setObjectName("custom");
    custom.resize(500, 200);
    custom.setStyleSheet("background-color:rgba(0,128,0,128);");

    window.show();

    return a.exec();
}

transparentwidget.hpp

#ifndef TRANSPARENTWIDGET_H
#define TRANSPARENTWIDGET_H

#include <QWidget>
#include <QStyleOption>
#include <QPainter>
#include <QDebug>
#include <QEvent>

// This widget shall be transparent in some parts
class TransparentWidget : public QWidget
{
    Q_OBJECT

public:
    explicit TransparentWidget(QWidget *parent = 0): QWidget(parent)
    {
        // Start of solution with WA_TransparentForMouseEvents (not working)
        setAttribute(Qt::WA_TransparentForMouseEvents);
        // end solution with WA_TransparentForMouseEvents
    }
    ~TransparentWidget(){}

protected:
    QRect opaqueRect = QRect(0,0,400,100);
    void paintEvent(QPaintEvent *)
    {
        // Solution with setMask, not working
        QRegion reg(opaqueRect);
        setMask(reg);
        // end of setMask solution

        QStyleOption opt;
        opt.init(this);
        QPainter p(this);
        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    }

    bool event(QEvent *event)
    {
        // Starting of solution with event propagation (not working)
        if (event->type() == QEvent::MouseButtonPress ||
            event->type() == QEvent::MouseButtonRelease)
        {
            QMouseEvent* e = static_cast<QMouseEvent*>(event);
            if (e && !opaqueRect.contains(e->pos()) return false;
        }
        // end solution with event propagation.

        if (event->type() == QEvent::MouseButtonPress) qDebug() << "Press: " << objectName();
        else if(event->type() == QEvent::MouseButtonRelease) qDebug() << "Release: " << objectName();

        return QWidget::event(event);
    }
};
#endif

normalwidget.hpp

#ifndef NORMALWIDGET_H
#define NORMALWIDGET_H

#include <QWidget>
#include <QStyleOption>
#include <QPainter>
#include <QDebug>
#include <QEvent>

// Widgets that are not event-transparent
class NormalWidget : public QWidget
{
    Q_OBJECT

public:
    explicit NormalWidget(QWidget *parent = 0): QWidget(parent){}
    ~NormalWidget(){}

protected:
    void paintEvent(QPaintEvent *)
    {
        QStyleOption opt;
        opt.init(this);
        QPainter p(this);
        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    }

    bool event(QEvent *event)
    {

        if (event->type() == QEvent::MouseButtonPress) qDebug() << "Press: " << objectName();
        else if(event->type() == QEvent::MouseButtonRelease) qDebug() << "Release: " << objectName();

    }
};

#endif // NORMALWIDGET_H

1 个答案:

答案 0 :(得分:0)

就像文档说的那样:

  

启用后,此属性将禁用鼠标事件的传递   小部件和其子级

解决方案是忽略TransparentWidget::event()内的所有鼠标事件。如果对TransparentWidget的孩子进行鼠标事件,则该事件将由孩子使用,否则将被传递给TransparentWidget的父母:

bool TransparentWidget::event(QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress ||
        event->type() == QEvent::MouseButtonRelease ||
        event->type() == QEvent::MouseButtonRelease)
        return false;
    else
        return QWidget::event(event);
}