C’è un modo per sfocare un widget in Qt? Ad esempio, in primo luogo desidero creare una finestra di dialogo “Caricamento in corso …” e sfocare lo sfondo (finestra non triggers).
Questa risposta è in una serie di risposte relative alla sovrapposizione: primo , secondo , terzo .
Richiede una certa caucanvas se si desidera che funzioni su tutte le piattaforms. Non è ansible applicare effetti direttamente alle windows di livello superiore. La gerarchia deve apparire come segue:
ContainerWidget | +----------+ | | **Target** Overlay
Applica l’effetto al widget Target
(ad esempio, una QMainWindow
). Il ContainerWidget
è una class di supporto che mantiene i bambini che occupano l’intera dimensione del widget. Ciò ovvia alla necessità di un esplicito layout a margine zero.
Il sotto funziona, anche su un Mac. Non sarebbe, se avessi rinunciato al ContainerWidget
. Sfortunatamente funziona solo su Qt 5. In Qt 4, il supporto “multipiattaforma” esclude Mac 🙁 Funziona correttamente su Windows utilizzando Qt 4 (4.8.5) o Qt 5.
// https://github.com/KubaO/stackoverflown/tree/master/questions/overlay-blur-19383427 #include #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) #include #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(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(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(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); } }; namespace compat { #if QT_VERSION >= QT_VERSION_CHECK(5,4,0) using QT_PREPEND_NAMESPACE(QTimer); #else using Q_QTimer = QT_PREPEND_NAMESPACE(QTimer); class QTimer : public Q_QTimer { public: QTimer(QTimer *parent = nullptr) : Q_QTimer(parent) {} template static 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(fun)) { timer.start(period, this); } }; new Helper(period, std::forward (fun)); } }; #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(); compat::QTimer::singleShot(2000, [&]{ overlay.hide(); label.setGraphicsEffect({}); }); return a.exec(); }
Vedi QGraphicsBlurEffect Class
e QWidget::setGraphicsEffect()
.
È ansible fare riferimento a questo articolo se si desidera applicare l’effetto sfocatura su un’immagine. Dopo aver creato l’immagine sfocata, puoi disegnarla nella funzione QWidget::paintEvent()
.