Dark transparent layer over a QMainWindow in Qt(Qt 中 QMainWindow 上的深色透明层)
问题描述
我需要在我的应用程序中实现一个加载..."窗口,但我更喜欢用上面有文本的深色透明层覆盖整个 QMainWindow.有人知道怎么做吗?我不确定如何在 Qt 中重叠小部件/布局.任何帮助将不胜感激.
这个答案是在我与叠加层相关的一系列答案中:
//https://github.com/KubaO/stackoverflown/tree/master/questions/overlay-widget-19362455#include #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)#include #万一类 OverlayWidget : 公共 QWidget{void newParent() {如果 (!parent()) 返回;parent()->installEventFilter(this);增加();}民众:显式 OverlayWidget(QWidget * parent = {}) : QWidget{parent} {setAttribute(Qt::WA_NoSystemBackground);setAttribute(Qt::WA_TransparentForMouseEvents);newParent();}受保护://!从父小部件捕获调整大小和子事件bool eventFilter(QObject * obj, QEvent * ev) 覆盖 {如果(对象==父()){if (ev->type() == QEvent::Resize)resize(static_cast(ev)->size());else if (ev->type() == QEvent::ChildAdded)增加();}返回 QWidget::eventFilter(obj, ev);}//!跟踪父小部件更改布尔事件(QEvent* ev)覆盖{if (ev->type() == QEvent::ParentAboutToChange) {if (parent()) parent()->removeEventFilter(this);}else if (ev->type() == QEvent::ParentChange)newParent();返回 QWidget::event(ev);}};类 LoadingOverlay : 公共 OverlayWidget{民众:LoadingOverlay(QWidget * parent = {}) : OverlayWidget{parent} {setAttribute(Qt::WA_TranslucentBackground);}受保护:无效paintEvent(QPaintEvent *)覆盖{QPainter p{this};p.fillRect(rect(), {100, 100, 100, 128});p.setPen({200, 200, 255});p.setFont({"arial,helvetica", 48});p.drawText(rect(), "Loading...", Qt::AlignHCenter | Qt::AlignVCenter);}};int main(int argc, char * argv[]){QApplication a{argc, argv};QMainWindow 窗口;QLabel 中央{"你好"};central.setAlignment(Qt::AlignHCenter | Qt::AlignTop);central.setMinimumSize(400, 300);LoadingOverlay 叠加{¢ral};QTimer::singleShot(5000, &overlay, SLOT(hide()));window.setCentralWidget(¢ral);window.show();返回 a.exec();}
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.
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.
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.
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.
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.
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.
// https://github.com/KubaO/stackoverflown/tree/master/questions/overlay-widget-19362455
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
class OverlayWidget : public QWidget
{
void newParent() {
if (!parent()) return;
parent()->installEventFilter(this);
raise();
}
public:
explicit OverlayWidget(QWidget * parent = {}) : QWidget{parent} {
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
newParent();
}
protected:
//! Catches resize and child events from the parent widget
bool eventFilter(QObject * obj, QEvent * ev) override {
if (obj == parent()) {
if (ev->type() == QEvent::Resize)
resize(static_cast<QResizeEvent*>(ev)->size());
else if (ev->type() == QEvent::ChildAdded)
raise();
}
return QWidget::eventFilter(obj, ev);
}
//! Tracks parent widget changes
bool event(QEvent* ev) override {
if (ev->type() == QEvent::ParentAboutToChange) {
if (parent()) parent()->removeEventFilter(this);
}
else if (ev->type() == QEvent::ParentChange)
newParent();
return QWidget::event(ev);
}
};
class LoadingOverlay : public OverlayWidget
{
public:
LoadingOverlay(QWidget * parent = {}) : OverlayWidget{parent} {
setAttribute(Qt::WA_TranslucentBackground);
}
protected:
void paintEvent(QPaintEvent *) override {
QPainter p{this};
p.fillRect(rect(), {100, 100, 100, 128});
p.setPen({200, 200, 255});
p.setFont({"arial,helvetica", 48});
p.drawText(rect(), "Loading...", Qt::AlignHCenter | Qt::AlignVCenter);
}
};
int main(int argc, char * argv[])
{
QApplication a{argc, argv};
QMainWindow window;
QLabel central{"Hello"};
central.setAlignment(Qt::AlignHCenter | Qt::AlignTop);
central.setMinimumSize(400, 300);
LoadingOverlay overlay{¢ral};
QTimer::singleShot(5000, &overlay, SLOT(hide()));
window.setCentralWidget(¢ral);
window.show();
return a.exec();
}
这篇关于Qt 中 QMainWindow 上的深色透明层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Qt 中 QMainWindow 上的深色透明层


基础教程推荐
- 常量变量在标题中不起作用 2021-01-01
- 我有静态或动态 boost 库吗? 2021-01-01
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 如何通过C程序打开命令提示符Cmd 2022-12-09
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 这个宏可以转换成函数吗? 2022-01-01