26

我试图淡入和淡出一个QLabel或任何子QWidget类。我已经尝试过QGraphicsEffect,但不幸的是它只在 Windows 上运行良好,在 Mac 上不行。

唯一可以在 Mac 和 Windows 上运行的其他解决方案似乎有我自己的自定义paintEvent,我在其中设置不透明度,QPainterQ_PROPERTY在派生中定义“不透明度”QLabel并通过QPropertyAnimation.

我将粘贴在相关代码段下方供您参考。我仍然在这里看到一个问题 - 重用似乎QLabel::paintEvent不起作用,只有当我使用我想淡出子类,那是一场噩梦。请澄清我是否在这里犯了任何明显的错误。QPainterQWidget

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);
}
4

4 回答 4

43

实际上有一种超级简单的方法可以做到这一点,没有混乱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.
于 2015-10-07T06:24:06.400 回答
2

尝试将调色板的某些部分公开为标签的属性,然后对其进行动画处理:

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的新插值器来避免子类化,但这有点复杂。

于 2013-09-30T09:17:10.697 回答
1

您可以将小部件放入QGraphicsScene. 它支持不透明度变化和动画。

QGraphicsProxyWidget有关示例,请参阅文档。

于 2013-09-30T08:15:01.393 回答
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});")

这样做的原因是我们没有为属性设置动画。相反,我们正在为浮点值设置动画,但关键是每次浮点值更改时,我们都会获取它的值并将其传递给执行我们自定义工作的自定义函数(在我们的例子中,通过样式表设置不透明度)

于 2021-07-26T08:55:21.020 回答