模糊效果QWidget在Qt [英] Blur effect over a QWidget in Qt
问题描述
有什么办法在Qt模糊一个小部件吗?例如,假设我要创建一个正在加载...对话框并模糊背景(非活动窗口)。
Is there any way to blur a widget in Qt? For instance, supose I want to create a 'Loading...' dialog and blur the background (not active window).
推荐答案
此答案位于一系列与我重叠式广告相关的答案中:第一,第二,第三。
This answer is in a series of my overlay-related answers: first, second, third.
如果你希望它在所有平台上工作,它需要一些注意。您不能将效果直接应用到顶级窗口。层次结构需要如下:
It requires some care if you wish for it to work on all platforms. You can't apply effects directly to top-level windows. The hierarchy needs to look as follows:
ContainerWidget
|
+----------+
| |
**Target** Overlay
将效果应用于目标
小部件(例如, QMainWindow
)。 ContainerWidget
是一个帮助器类,用于保持子元素占用该窗口小部件的完整大小。这样就不需要显式的零边距布局。
You apply the effect to the Target
widget (say, a QMainWindow
). The ContainerWidget
is a helper class that keeps the children occupying the full size of the widget. This obviates the need for an explicit zero-margin layout.
下面的工作,即使在Mac上。它不会,你已经放弃 ContainerWidget
。这只工作在可移植的Qt 5,不幸的是。在Qt 4,你的跨平台支持排除了Mac :(它在Windows上使用Qt 4(4.8.5)或Qt 5工作正常。
The below works, even on a Mac. It wouldn't, had you foregone the ContainerWidget
. This works portably on Qt 5 only, unfortunately. On Qt 4, your "cross platform" support excludes Mac :( It works OK on Windows using either Qt 4 (4.8.5) or Qt 5.
#include <QApplication>
#include <QLabel>
#include <QResizeEvent>
#include <QPainter>
#include <QGraphicsBlurEffect>
#ifndef Q_DECL_OVERRIDE
#define Q_DECL_OVERRIDE override
#endif
class OverlayWidget : public QWidget
{
void newParent() {
if (!parent()) return;
parent()->installEventFilter(this);
raise();
}
public:
explicit OverlayWidget(QWidget * parent = 0) : QWidget(parent) {
setAttribute(Qt::WA_NoSystemBackground);
newParent();
}
protected:
//! Catches resize and child events from the parent widget
bool eventFilter(QObject * obj, QEvent * ev) Q_DECL_OVERRIDE {
if (obj == parent()) {
if (ev->type() == QEvent::Resize) {
QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
this->resize(rev->size());
}
else if (ev->type() == QEvent::ChildAdded) {
raise();
}
}
return QWidget::eventFilter(obj, ev);
}
//! Tracks parent widget changes
bool event(QEvent* ev) Q_DECL_OVERRIDE {
if (ev->type() == QEvent::ParentAboutToChange) {
if (parent()) parent()->removeEventFilter(this);
}
else if (ev->type() == QEvent::ParentChange) {
newParent();
}
return QWidget::event(ev);
}
};
class ContainerWidget : public QWidget
{
public:
explicit ContainerWidget(QWidget * parent = 0) : QWidget(parent) {}
inline void setSize(QObject * obj) {
if (obj->isWidgetType()) static_cast<QWidget*>(obj)->setGeometry(rect());
}
protected:
//! Resizes children to fill the extent of this widget
bool event(QEvent * ev) Q_DECL_OVERRIDE {
if (ev->type() == QEvent::ChildAdded) {
setSize(static_cast<QChildEvent*>(ev)->child());
}
return QWidget::event(ev);
}
//! Keeps the children appropriately sized
void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE {
foreach(QObject * obj, children()) setSize(obj);
}
};
class LoadingOverlay : public OverlayWidget
{
public:
LoadingOverlay(QWidget * parent = 0) : OverlayWidget(parent) {
setAttribute(Qt::WA_TranslucentBackground);
}
protected:
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE {
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::AlignTop);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ContainerWidget base;
QLabel l("Dewey, Cheatem and Howe, LLC.", &base);
l.setFont(QFont("times,times new roman", 32));
l.setAlignment(Qt::AlignCenter);
l.setGraphicsEffect(new QGraphicsBlurEffect);
LoadingOverlay overlay(&base);
base.show();
return a.exec();
}
这篇关于模糊效果QWidget在Qt的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!