c++ - Qt QWidget隐藏动画

标签 c++ qt animation qwidget

我有一个 QWidget 的子类,它是一个弹出式小部件。我想在它显示和消失时添加一些动画。所以我重新实现了showEvent(QShowEvent * event)hideEvent,并在函数中添加了一些QPropertyAnimationshowEvent 对我来说效果很好,但 hideEvent 却不行。因为

Hide events are sent to widgets immediately after they have been hidden.

知道怎么做吗?

更新:

我不认为这是正确的理由。当我使用 Nejat 的解决方案时。表演部分有效。但是当我在小部件外部单击时。它立即消失。

最佳答案

您应该重写 QWidget::closeEvent() 以便在尝试立即关闭时它将被忽略并且我们开始动画并在完成后 (QPropertyAnimation::finished()) 我们正常关闭小部件。

这里有一个演示:

class AnimatedWidget : public QWidget {
    Q_OBJECT
        Q_PROPERTY(qreal alpha READ alpha WRITE setAlpha)

public:
    AnimatedWidget(QWidget* parent = nullptr) :QWidget{ parent }, opacityAnimation{ new QPropertyAnimation{this, "alpha",this} } {
        setWindowFlags(windowFlags() | Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::Tool);
        auto pal = palette();
        pal.setColor(QPalette::Background, Qt::cyan);
        setAutoFillBackground(true);
        setPalette(pal);
        setFixedSize(200, 200);
    }

    qreal alpha() const {
        return windowOpacity();
    }

    void setAlpha(qreal level) {
        setWindowOpacity(level);
        update();
    }

protected:
    void closeEvent(QCloseEvent* e) override {
        if (opacityAnimation->currentValue().toReal() == 1.0) { // Ignore event + start animation
            e->ignore();
            startHide();
            QObject::connect(opacityAnimation, SIGNAL(finished()), this, SLOT(onAnimationCallBack()), Qt::UniqueConnection);
        } else {
            e->accept();
            if (!isHidden())
                hide();
            QWidget::close(); // necessary actions
        }
    }

    public Q_SLOTS:
    void show() {
        startShow();
        QWidget::show(); // necessary actions
    }

    private Q_SLOTS:
    void onAnimationCallBack() {
        if (opacityAnimation->currentValue().toReal() == 0.0) { // we're finished so let's really close the widget
            QCloseEvent ev;
            QApplication::sendEvent(this, &ev);
            qApp->sendEvent(this, &ev);
        }
    }

    void startHide() {
        opacityAnimation->setStartValue(1.0);
        opacityAnimation->setEndValue(0.0);
        opacityAnimation->setDuration(1500);
        opacityAnimation->start();
    }

    void startShow() {
        opacityAnimation->setStartValue(0.0);
        opacityAnimation->setEndValue(1.0);
        opacityAnimation->setDuration(1500);
        opacityAnimation->start();
    }

private:
    QPropertyAnimation* opacityAnimation = nullptr;
};

class Base : public QWidget {
public:
    Base(QWidget* parent = nullptr) :QWidget{ parent }, widget{ new AnimatedWidget{} } {

    }

private:
    AnimatedWidget* widget;

protected:
    void mouseReleaseEvent(QMouseEvent* e) override {
        if (widget->isHidden())
            widget->show();
        else
            widget->close();
        QWidget::mouseReleaseEvent(e);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    Base base;
    base.show();
    return app.exec();
}

enter image description here

关于c++ - Qt QWidget隐藏动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23611738/

相关文章:

jquery - 寻找一种在 div 之间滑动底部边框的方法

c++ - 如何确定与套接字的连接是否已关闭

c++ - ListView 控件因列数过多而性能下降

c++ - 最后一次使用可 move 对象时,编译器会自动使用 move 语义吗?

c++ - 访问 Qt 小部件线程安全

css - 为什么 css 动画(没有 JS)不起作用?

c++ - 在 Qt 中调整 ./configure 步骤

c++ - 编写可以处理隐式共享但对不可复制类型(如 unique_ptr)关闭它的容器?

c++ - QScrollArea 缺少滚动条

c# - 简单的按钮动画