Как заставить виджеты Qt исчезать или исчезать?

Я пытаюсь затухать и исчезать QLabel или, в этом отношении, любой подкласс QWidget. Я попытался с QGraphicsEffect, но, к сожалению, он работает хорошо только на Windows, а не на 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);
}

Ответ 1

На самом деле это очень простой способ сделать это без беспорядочного перехвата QPaintEvent и без жестких требований QGraphicsProxyWidget, который не работает на продвинутых дочерних QPaintEvent. Нижеприведенная техника будет работать даже с продвинутыми виджетами и видениями их детей.

Fade In Your Widget

// 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.

Ответ 2

Вы можете поместить свои виджеты в QGraphicsScene. Он поддерживает изменение непрозрачности и анимацию.

Для примера см. Документацию QGraphicsProxyWidget.

Ответ 3

Попробуйте выставить некоторую часть палитры как свойство метки, а затем оставьте ее:

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, но это немного сложно.