暗透明层QMainWindow在Qt [英] Dark transparent layer over a QMainWindow in Qt

查看:225
本文介绍了暗透明层QMainWindow在Qt的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在我的应用程序中实现一个加载...窗口,但我更喜欢覆盖整个QMainWindow与一个黑暗的透明层上面的文本。有人知道如何做到吗?我不知道如何重叠小部件/布局在Qt。

I need to implement a "Loading..." window in my application but I do prefer to cover the whole QMainWindow with a dark transparent layer with a text above. Does anybody know how to do that? I am not sure how to overlap widgets/layouts in Qt. Any help will be appreciated.

推荐答案

这个答案是在一系列我的叠加层相关的答案:第一次第三版

This answer is in a series of my overlay-related answers: first, second, third.

最简单的解决方案是简单地添加子透明小部件 QMainWindow 。该窗口小部件必须仅跟踪其父窗口的大小。正确处理窗口小部件父级的更改以及与兄弟姐妹的z顺序很重要。

The most trivial solution is to simply add a child transparent widget to QMainWindow. That widget must merely track the size of its parent window. It is important to properly handle changes of widget parentage, and the z-order with siblings. Below is a correct example of how to do it.

如果你想叠加叠加,后续叠加应该是 OverlayWidget ,在z顺序。如果他们是 OverlayWidget 的兄弟姐妹,他们的堆叠顺序是未定义的。

If you want to stack overlays, subsequent overlays should be the children of OverlayWidget, in the z-order. If they were to be siblings of the OverlayWidget, their stacking order is undefined.

提供与其他代码的最小耦合。它不需要任何知识从应用覆盖到的小部件。您可以将覆盖应用于 QMainWindow 或任何其他窗口小部件,窗口小部件也可以在布局中。

This solution has the benefit of providing minimal coupling to other code. It doesn't require any knowledge from the widget you apply the overlay to. You can apply the overlay to a QMainWindow or any other widget, the widget can also be in a layout.

重新实现 QMainWindow 的paint事件不会被认为是最好的设计。它使它绑定到一个特定的类。如果你真的认为一个 QWidget 实例是太多的开销,你最好有测量显示是这种情况。

Reimplementing QMainWindow's paint event would not be considered the best design. It makes it tied to a particular class. If you really think that a QWidget instance is too much overhead, you better had measurements to show that being the case.

当然,可以使覆盖只有一个 QObject ,并将绘画代码放入事件过滤器。这将是一个替代解决方案。这很难做,因为你还必须正确处理父窗口小部件的 Qt :: WA_StaticContents 属性,并且该窗口小部件可能调用其 scroll() 方法。处理单独的小部件是最简单的。

It is possible, of course, to make the overlay merely a QObject and to put the painting code into an event filter. That'd be an alternative solution. It's harder to do since you have to also properly deal with the parent widget's Qt::WA_StaticContents attribute, and with the widget potentially calling its scroll() method. Dealing with a separate widget is the simplest.

#include <QApplication>
#include <QMainWindow>
#include <QResizeEvent>
#include <QPainter>

class OverlayWidget : public QWidget
{
public:
    explicit OverlayWidget(QWidget * parent = 0) : QWidget(parent) {
        if (parent) {
            parent->installEventFilter(this);
            raise();
        }
    }
protected:
    //! Catches resize and child events from the parent widget
    bool eventFilter(QObject * obj, QEvent * ev) {
        if (obj == parent()) {
            if (ev->type() == QEvent::Resize) {
                QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
                resize(rev->size());
            }
            else if (ev->type() == QEvent::ChildAdded) {
                raise();
            }
        }
        return QWidget::eventFilter(obj, ev);
    }
    //! Tracks parent widget changes
    bool event(QEvent* ev) {
        if (ev->type() == QEvent::ParentAboutToChange) {
            if (parent()) parent()->removeEventFilter(this);
        }
        else if (ev->type() == QEvent::ParentChange) {
            if (parent()) {
                parent()->installEventFilter(this);
                raise();
            }
        }
        return QWidget::event(ev);
    }
};

class LoadingOverlay : public OverlayWidget
{
public:
    LoadingOverlay(QWidget * parent = 0) : OverlayWidget(parent) {
        setAttribute(Qt::WA_TranslucentBackground);
    }
protected:
    void paintEvent(QPaintEvent *) {
        QPainter p(this);
        p.fillRect(rect(), QColor(100, 100, 100, 128));
        p.setPen(QColor(200, 200, 255, 255));
        p.setFont(QFont("arial,helvetica", 48));
        p.drawText(rect(), "Loading...", Qt::AlignHCenter | Qt::AlignVCenter);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QMainWindow w;
    new LoadingOverlay(&w);
    w.show();
    return a.exec();
}

这篇关于暗透明层QMainWindow在Qt的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆