Эффект размытия над QWidget в Qt

Есть ли способ размыть виджет в Qt? Например, предположим, что я хочу создать диалог «Загрузка …» и размыть фон (не активное окно).

Этот ответ находится в серии моих ответов, связанных с оверлей: первый , второй , третий .

Это требует некоторой осторожности, если вы хотите, чтобы он работал на всех платформах. Вы не можете применять эффекты непосредственно к windowsм верхнего уровня. Иерархия должна выглядеть следующим образом:

ContainerWidget | +----------+ | | **Target** Overlay 

Эффект применяется к Target (скажем, QMainWindow ). ContainerWidget – это вспомогательный class, в котором дети занимают полный размер виджета. Это устраняет необходимость в явном макете с нулевым краем.

Нижеследующее работает, даже на Mac. Это не так, если бы вы отказались от ContainerWidget . К сожалению, это работает только на Qt 5. На Qt 4 ваша поддержка «кросс-платформы» исключает Mac 🙁 Он работает нормально в Windows, используя либо Qt 4 (4.8.5), либо 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(); } 

См. QGraphicsBlurEffect Class и QWidget::setGraphicsEffect() .

Вы можете обратиться к этой статье, если хотите применить эффект размытия изображения. После создания размытого изображения вы можете нарисовать его в функции QWidget::paintEvent() .

  • Обнаруживать, является ли stdin терминалом или трубой?
  • Получить индекс QPushButton на 2D-массиве QPushButton
  • Легкий интерфейс MySQL Qt GUI для Linux
  • Как скомпилировать Qt 5 под Windows или Linux, 32 или 64 бит, статические или динамические на VS2010, VS2012, VS2013 или VS2015 Express или g ++
  • Как указать разные каталоги вывода отладки / выпуска в файле QMake .pro
  • Возможно ли подключить сигнал к статическому слоту без экземпляра приемника?
  • Темный прозрачный слой над QMainWindow в Qt
  • Как связать opencv в QtCreator и использовать библиотеку Qt
  • Beyond Stack Sampling: C ++ Profilers
  • Как создать функцию pause / wait с помощью Qt?
  • Совместимость Ncurses и Qt
  • Давайте будем гением компьютера.