我正在尝试淡入淡出QLabel
或淡出任何QWidget
子类。我尝试使用QGraphicsEffect
,但不幸的是它仅适用于Windows而不适用于Mac。
唯一可以同时适用于Mac和Mac的解决方案Windows似乎有我自己的自定义paintEvent
,其中我设置QPainter
的不透明度,并为"不透明度定义Q_PROPERTY
"在我的派生QLabel
中,通过QPropertyAnimation
更改不透明度。
我粘贴在相关代码段下方供您参考。我仍然在这里看到一个问题 - 重复使用QLabel::paintEvent
似乎无法正常工作,只有在使用QPainter
进行完整的自定义绘画时,它才有效,但这似乎并不现象这是一个简单的方法,如果我需要为每个我要淡出的QWidget
子类做到这一点,那就是一场噩梦。请澄清我是否在这里犯了任何明显的错误。
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
void MyLabel::setOpacity(qreal value) {
m_Opacity = value;
repaint();
}
void MyLabel::paintEvent((QPaintEvent *pe) {
QPainter p;
p.begin(this);
p.setOpacity();
QLabel::paintEvent(pe);
p.end();
}
void MyLabel::startFadeOutAnimation() {
QPropertyAnimation *anim = new QPropertyAnimation(this, "opacity");
anim->setDuration(800);
anim->setStartValue(1.0);
anim->setEndValue(0.0);
anim->setEasingCurve(QEasingCurve::OutQuad);
anim->start(QAbstractAnimation::DeleteWhenStopped);
}
答案 0 :(得分:28)
实际上有一种非常简单的方法可以做到这一点而不会出现凌乱的QPaintEvent
拦截并且没有QGraphicsProxyWidget
的严格要求,这对于提升的小部件子项不起作用。下面的技术甚至可以用于推广的小部件及其子窗口小部件。
淡入您的小工具
// w is your widget
QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
w->setGraphicsEffect(eff);
QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
a->setDuration(350);
a->setStartValue(0);
a->setEndValue(1);
a->setEasingCurve(QEasingCurve::InBack);
a->start(QPropertyAnimation::DeleteWhenStopped);
淡出您的小工具
// w is your widget
QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
w->setGraphicsEffect(eff);
QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
a->setDuration(350);
a->setStartValue(1);
a->setEndValue(0);
a->setEasingCurve(QEasingCurve::OutBack);
a->start(QPropertyAnimation::DeleteWhenStopped);
connect(a,SIGNAL(finished()),this,SLOT(hideThisWidget()));
// now implement a slot called hideThisWidget() to do
// things like hide any background dimmer, etc.
答案 1 :(得分:1)
您可以将小部件放入QGraphicsScene
。它支持不透明度变化和动画。
有关示例,请参阅QGraphicsProxyWidget
文档。
答案 2 :(得分:1)
尝试将调色板的某些部分公开为标签的属性,然后为其设置动画:
Q_PROPERTY(QColor color READ color WRITE setColor)
void MyLabel::setColor(const QColor &value) {
QPalette palette;
palette.setBrush(QPalette::WindowText, value);
setPalette(palette);
}
QColor MyLabel::color() {
return palette(QPalette::Normal, QPalette::Window).
}
void MyLabel::startFadeOutAnimation() {
QPropertyAnimation *animation = new QPropertyAnimation(label, "color", this);
QColor c = label->color();
animation->setKeyValueAt(0, c);
c.setAlpha(0);
animation->setKeyValueAt(1, c);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setDuration(1000);
animation->start(QAbstractAnimation::DeleteWhenStopped);
}
您可以尝试通过定义和注册将处理QPalette qRegisterAnimationInterpolator的新插值器来避免子类化,但这有点复杂。
答案 3 :(得分:0)
很抱歉我不能用 C++ 编写它,但是在 python3 和 C++ 中的实现是相同的:
您可以创建一个 QVariantAnimation 动画表示不透明度的浮点值,将 valueChanged
信号连接到自定义函数:
anim = QVariantAnimation()
anim.setStartValue(.3)
anim.setEndValue(.6)
anim.setDuration(900)
anim.setEasingCurve(QEasingCurve.InOutQuad) # Not strictly required, just for the aesthetics
anim.valueChanged.connect(lambda opacity: mySpecialFun(opacity))
anim.start()
然后,定义更改不透明度(或要设置动画的属性)的自定义函数:
def mySpecialFun(opacity: float) -> None:
mywidget.setStyleSheet(f"background-color: rgba(0, 0, 0, {color});")
这样做的原因是我们没有为属性设置动画。相反,我们正在为浮点值设置动画,但关键是每次浮点值更改时,我们都会获取其值并将其传递给执行自定义作业的自定义函数 (在我们的示例中,通过样式表设置不透明度)