简体   繁体   English

Qt QWidget隐藏动画

[英]Qt QWidget hide animation

I have a sub-class of QWidget that is a popup widget. 我有一个QWidget的子类,它是一个弹出窗口小部件。 I would like to add some animation when it shows and disappears. 我想在它显示和消失时添加一些动画。 So I re-implemented showEvent(QShowEvent * event) and hideEvent and added some QPropertyAnimation in the functions. 所以我重新实现了showEvent(QShowEvent * event)hideEvent并在函数中添加了一些QPropertyAnimation The showEvent works just fine for me but the hideEvent doesn't. showEvent对我来说很好,但hideEvent没有。 Because 因为

Hide events are sent to widgets immediately after they have been hidden. 隐藏事件在隐藏后立即发送到窗口小部件。

Any idea about how to do it? 有什么想法怎么做?

Update: 更新:

I don't think it's the right reason. 我不认为这是正确的理由。 When I use Nejat's solution. 当我使用Nejat的解决方案时。 The show part works. 节目部分有效。 But when I click outside the widget. 但是当我在小部件外面点击时。 It disappears immediately. 它立即消失。

You should override QWidget::closeEvent() so when trying to close immediatly it will be ignored AND we start our animation and after finishing ( QPropertyAnimation::finished() ) we close the widget as normal. 你应该覆盖QWidget::closeEvent()所以当试图立即关闭时它将被忽略并且我们开始动画并在完成后( QPropertyAnimation::finished() )我们正常关闭小部件。

Here is a demo to demonstrate: 这是一个演示来演示:

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

在此输入图像描述

You can override the eventFilter in your widget and check for QEvent::Show and QEvent::Close events. 您可以覆盖窗口小部件中的eventFilter并检查QEvent::ShowQEvent::Close事件。

bool MyWidget::eventFilter(QObject * obj, QEvent * event)
{
    if(obj == this && event->type() == QEvent::Show)
    {
        //about to show
    }
    else if(obj == this && event->type() == QEvent::Close)
    {
        //about to close
    }


    return false;
}

You should also install the event filter in the constructor by: 您还应该通过以下方式在构造函数中安装事件过滤器:

this->installEventFilter(this);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM