Creating a dark overlay to apply on top of other widgets
Unsolved
General and Desktop
-
Hi, I want to be able to create a dark overlay on top of other widgets that can be turned on or of with animation, so for I have this
OverlayWidget.h
#pragma once #include <QObject> #include <QFrame> #include <QGraphicsOpacityEffect> #include <QPropertyAnimation> #include <QPaintEvent> #include <QMouseEvent> class OverlayWidget : public QWidget { Q_OBJECT public: explicit OverlayWidget(QWidget* parent = nullptr, const int duration = 370); void show(const bool& show = true); signals: void pressed(); // used for close the overlay when its opened and user click on it private: QGraphicsOpacityEffect fade_effect; QPropertyAnimation animation; protected: void mousePressEvent(QMouseEvent* event); void paintEvent(QPaintEvent* event); bool eventFilter(QObject* obj, QEvent* ev) override; bool event(QEvent* ev) override; private: void newParent(); };
OverlayWidget.cpp
#include "Overlay.h" #include <QPainter> #include <QDebug> OverlayWidget::OverlayWidget(QWidget* parent, const int duration) : QWidget{ parent } , fade_effect(this) , animation(&fade_effect, "opacity") { setPalette(Qt::transparent); setAttribute(Qt::WA_NoSystemBackground); newParent(); // setStyleSheet("border-radius:8;"); setGraphicsEffect(&fade_effect); animation.setStartValue(0.0); animation.setEndValue(1.0); animation.setEasingCurve(QEasingCurve::InOutQuint); animation.setDuration(duration); setVisible(false); setEnabled(false); } void OverlayWidget::newParent() { if (!parent()) return; parent()->installEventFilter(this); raise(); } bool OverlayWidget::eventFilter(QObject* obj, QEvent* ev) { 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); } bool OverlayWidget::event(QEvent* ev) { if (ev->type() == QEvent::ParentAboutToChange) { if (parent()) parent()->removeEventFilter(this); } else if (ev->type() == QEvent::ParentChange) newParent(); return QWidget::event(ev); } void OverlayWidget::show(const bool& show) { animation.stop(); animation.setStartValue(animation.currentValue()); animation.setEndValue(show ? 1.0 : 0.0); // show or hide animation.start(); if (show) { setVisible(true); setEnabled(true); setAttribute(Qt::WA_TransparentForMouseEvents, false); } else { // setVisible(false); setEnabled(false); setAttribute(Qt::WA_TransparentForMouseEvents); } } void OverlayWidget::paintEvent(QPaintEvent* event) { Q_UNUSED(event); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(QBrush(QColor(0, 0, 0, 150))); painter.setOpacity(50); painter.setPen(Qt::NoPen); painter.drawRoundedRect(rect(), 8.0, 8.0); // becasue my frame is round } void OverlayWidget::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) emit pressed(); }
so far its work, but I think Im doing it very bad... any suggestion on how to improve it?
-
Here is the same question with a working example
https://codereview.stackexchange.com/questions/274781/qt-creating-a-dark-overlay-to-apply-on-top-of-other-widgets-with-animation