Unexpected behaviour with QGraphicsOpacityEffect and custom widgets
-
I've a custom widget
A
with custom event filter function.
On Enter/Leave event I trigger aQGraphicsOpacityEffect
on other custom widgetB
to fades in/out it with aQPropertyAnimation
.
B
has custom Enter/Leave event function that change an internal base widget (simply change a QPixmap).
If I enter inA
,B
correctly fades-in , but as soon as I enter inB
, it disappears (it callsPaint
and paints a transparent widget).
If I leaveA
thenB
comes back for duration ofQPropertyAnimation
.This behaviour doesn't appear when using
QGraphicsBlurEffect
Blur video
Opacity videoI really don't know why it does this with opacity, the function are the same...
-
Hi,
Which version of Qt are you using ?
Can you provide a minimal compilable example reproducing this ? -
Hi,
Which version of Qt are you using ?
Can you provide a minimal compilable example reproducing this ?@SGaist Hi, maybe I found a where the error is creating a minimal compilable example reproducing this.
I'm using Qt6.3
This isB
B.hclass B : public QWidget{ Q_OBJECT public: B(const QPixmap& icon, QWidget* parent = nullptr); signals: void clicked(); protected: bool eventFilter(QObject* obj, QEvent* event) override; private: void updateIcon(); QLabel* labelIcon; QPixmap icon; };
B.cpp
B::B(const QPixmap& icon, QWidget* parent): QWidget(parent){ QHBoxLayout* base_layout = new QHBoxLayout; labelIcon = new QLabel; this->icon = icon; base_layout->addWidget(labelIcon); installEventFilter(this); setLayout(base_layout); updateIcon(); } void B::updateIcon() { labelIcon->setPixmap(icon); } bool B::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::MouseButtonRelease) emit clicked(); //QEvent::Enter do something and than call update icon if (event->type() == QEvent::Enter) updateIcon(); //QEvent::Leave do something and than call update icon if (event->type() == QEvent::Leave) updateIcon(); return QObject::eventFilter(obj, event); }
This is
A
A.hclass A : public QWidget { Q_OBJECT public: A(QWidget *parent = nullptr); protected: bool eventFilter(QObject* obj, QEvent* event) override; private: QPropertyAnimation* fadeAnimation; };
A.cpp
A::A(QWidget* parent) : QWidget(parent){ //init layout QVBoxLayout* mainLayout = new QVBoxLayout; installEventFilter(this); setLayout(mainLayout); setCursor(Qt::PointingHandCursor); installEventFilter(this); //wrap widget to create nested graphic effect widget! QWidget* wrap = new QWidget(this); //CREATE B with a pixmap in it B* b = new B(QPixmap("pixmap.png")); // pixmap.png is a simple colored rectangle b->setParent(wrap); b->move(10, 10); b->setFixedSize(60, 40); wrap->show(); QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect; shadow->setOffset(0, 0); shadow->setColor(QColor(60, 60, 60, 255)); shadow->setBlurRadius(5); QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect; opacityEffect->setOpacity(0); b->setGraphicsEffect(opacityEffect); wrap->setGraphicsEffect(shadow); fadeAnimation = new QPropertyAnimation(opacityEffect, "opacity"); fadeAnimation->setDuration(500); } bool A::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::Enter) { fadeAnimation->setStartValue(0); fadeAnimation->setEndValue(1); fadeAnimation->setEasingCurve(QEasingCurve::InBack); fadeAnimation->start(); } if (event->type() == QEvent::Leave) { fadeAnimation->setStartValue(1); fadeAnimation->setEndValue(0); fadeAnimation->setEasingCurve(QEasingCurve::InBack); fadeAnimation->start(); } return QObject::eventFilter(obj, event); }
In
main.cpp
createA
and then move your mouse over the image you loaded and you will see it will disappear.
I found out that if I swap grapfic effect (b
get shadow andwrap
get opacity) I get a lot of warning when B disappear. This is the output:Warning QPainter::begin: A paint device can only be painted by one painter at a time. Warning QPainter::translate: Painter not active Warning QPainter::worldTransform: Painter not active Warning QWidgetEffectSourcePrivate::pixmap: Painter not active Warning QPainter::worldTransform: Painter not active Warning QPainter::setWorldTransform: Painter not active Warning QPainter::setWorldTransform: Painter not active
So my try to nest two graphic effect failed totally, indeed if I remove shadow effect it does not trigger this behaviour.
EDIT: I tried to remove second effect in my main code but there is still the behaviour, only with opacity. Maybe it overlaps Paint function and the error is triggered, but no warning in console this time
-
I made some step on this error.
Based on this answer if I set nullptr on graphiceffect after propertyanimation the error disappear, but I lose the fade-out effect.Seems to be a bug since QGraphicEffect calls a paint event while the widget is painting the inner elements, triggering the warning and failing the paint at all
EDIT: seems like qgrapficeffects is propagated on all inner element, or at least goes in conflict with inner elements
-
Which version of Qt 6.3 are you using ?
-
@SGaist I'm using 6.3.0 with msvc compiler