में QWidget पर धुंध प्रभाव Qt में विजेट को धुंधला करने का कोई तरीका है? उदाहरण के लिए, मान लीजिए कि मैं 'लोड हो रहा हूं ...' संवाद बनाना चाहता हूं और पृष्ठभूमि को धुंधला करना चाहता हूं (सक्रिय विंडो नहीं)।Qt
Qt
उत्तर
यह उत्तर मेरे ओवरले से संबंधित उत्तरों की एक श्रृंखला में है: first, second, third।
यदि आप सभी प्लेटफॉर्म पर काम करना चाहते हैं तो इसे कुछ देखभाल की आवश्यकता है। आप सीधे शीर्ष-स्तरीय विंडो पर प्रभाव लागू नहीं कर सकते हैं। पदानुक्रम कुछ ऐसा नज़र करने की जरूरत है:
ContainerWidget
|
+----------+
| |
**Target** Overlay
आप Target
विजेट के लिए प्रभाव लागू (जैसे कि, एक QMainWindow
)। ContainerWidget
एक सहायक वर्ग है जो बच्चों को विजेट के पूर्ण आकार पर कब्जा रखता है। यह एक स्पष्ट शून्य-मार्जिन लेआउट की आवश्यकता को रोकता है।
नीचे दिए गए काम, मैक पर भी। यह नहीं होगा, क्या आपने ContainerWidget
का आगाह किया था। यह दुर्भाग्य से केवल क्यूटी 5 पर काम करता है। Qt 4 पर, अपने "क्रॉस प्लेटफॉर्म" समर्थन शामिल नहीं मैक :(यह या तो क्यूटी 4 (4.8.5) या क्यूटी 5.
// https://github.com/KubaO/stackoverflown/tree/master/questions/overlay-blur-19383427
#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 ContainerWidget : public QWidget
{
public:
explicit ContainerWidget(QWidget * parent = {}) : QWidget{parent} {}
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) override {
if (ev->type() == QEvent::ChildAdded) {
setSize(static_cast<QChildEvent*>(ev)->child());
}
return QWidget::event(ev);
}
//! Keeps the children appropriately sized
void resizeEvent(QResizeEvent *) override {
for(auto obj : children()) setSize(obj);
}
};
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::AlignTop);
}
};
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
template <typename F> void singleShot(int period, F && fun) {
struct Helper : public QObject {
F fun;
QBasicTimer timer;
void timerEvent(QTimerEvent * event) override {
if (event->timerId() != timer.timerId()) return;
fun();
deleteLater();
}
Helper(int period, F && fun) : fun(std::forward<F>(fun)) {
timer.start(period, this);
}
};
new Helper(period, std::forward<F>(fun));
}
#else
template <typename... Args>
auto singleShot(Args&&... args) -> decltype(QTimer::singleShot(std::forward<Args>(args)...)) {
return QTimer::singleShot(std::forward<Args>(args)...);
}
#endif
int main(int argc, char *argv[])
{
QApplication a{argc, argv};
ContainerWidget base;
QLabel label("Dewey, Cheatem and Howe, LLC.", &base);
label.setFont({"times,times new roman", 32});
label.setAlignment(Qt::AlignCenter);
label.setGraphicsEffect(new QGraphicsBlurEffect);
LoadingOverlay overlay(&base);
base.show();
singleShot(2000, [&]{
overlay.hide();
label.setGraphicsEffect({});
});
return a.exec();
}
विंडोज पर ठीक काम करता है
QGraphicsBlurEffect Class
और QWidget::setGraphicsEffect()
देखें।
यदि आप किसी छवि पर धुंध प्रभाव लागू करना चाहते हैं तो आप this आलेख का संदर्भ ले सकते हैं। अपनी धुंधली छवि बनाने के बाद आप इसे QWidget::paintEvent()
फ़ंक्शन में खींच सकते हैं।