为模态QDialog实现淡入/淡出

时间:2015-03-13 11:54:45

标签: qt

QDialog有很多打开和关闭的功能,比如open(),show(),exec(),close(),hide()。我不知道重新实现哪个函数()。

//编辑:   在showEvent()函数中启动动画是一个不错的选择。

2 个答案:

答案 0 :(得分:3)

简短回答:void exec()

长答案:void exec()但是

您需要决定“淡入”工作的方式并了解如何使用QPropertyAnimation

例如,您可以更改对话框的不透明度:

#include <QPropertyAnimation>
int MyDialog::exec()
{
    this->setWindowOpacity(0.0);
    QPropertyAnimation* anim = new QPropertyAnimation(this, "windowOpacity");
    anim->setDuration(5000); // will take 5 seconds
    anim->setEasingCurve(QEasingCurve::OutBack); // just demonstration, there are a lot of curves to choose
    anim->setStartValue(0.0);
    anim->setEndValue(1.0);
    anim->start(QAbstractAnimation::DeleteWhenStopped);
    return QDialog::exec();
}

int main(int argc, char** argv)
{
    QApplication a(argc, argv);
    MyDialog w;

    int ret = w.exec();
    return a.exec();
}

您可以为Property定义的任何QObject制作动画,其他所有内容都使用不同的动画和持续时间

编辑:改编使用QDialog::exec(),在Qt4.8.5,Vs2008,Win7Professionalx64上测试 欢呼声

答案 1 :(得分:0)

覆盖QDialog::open是解决之道。与QDialog::exec不同,它将在调用QDialog::finished时立即返回。另外,文档建议不要使用exec。

enter image description here

下面的代码很好用。

class AnimatedDialog : public QDialog
{
    Q_OBJECT

public:
    explicit AnimatedDialog(QWidget* parent = nullptr);
    void animate(bool reverse = false);

    void done(int r) override;
    void open() override;

signals:
    void reverseAnimStarted();

private:
    bool animation_on = false;
};


AnimatedDialog::AnimatedDialog(QWidget* parent) : QDialog{parent}
{
    setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::Popup | Qt::NoDropShadowWindowHint);
    setAttribute(Qt::WA_TranslucentBackground); 

    connect(this, &AnimatedDialog::reverseAnimStarted,
        [this] {animation_on = true; });
}

// override showEvent if you call show instead
void AnimatedDialog::open()
{
    animate(false);
    QDialog::open();
}

void AnimatedDialog::done(int r)
{
    if (!animation_on) {
        animate(true);
        setResult(r);
        if (r == QDialog::Accepted)
            emit accepted();
        else if (r == QDialog::Rejected)
            emit rejected();

        emit finished(r);
    }
}

void AnimatedDialog::animate(bool reverse)
{

    auto animFade= new QPropertyAnimation(this, "windowOpacity", this);
    animFade->setDuration(400);
    animFade->setEasingCurve(QEasingCurve::Linear);

    auto pos1 = QPoint{ (parentWidget()->pos().x() + parentWidget()->width() / 2 - width() / 2) + 15,
        (parentWidget()->pos().y() + parentWidget()->height() + height() / 2) / 2 };

    auto pos2 = QPoint{ (parentWidget()->pos().x() + parentWidget()->width() / 2 - width() / 2) + 15,
        (parentWidget()->pos().y() + parentWidget()->height() + height() / 2) / 2 - 65 };

    auto animMove = new QPropertyAnimation(this, "pos", this);
    animMove->setDuration(250);
    animMove->setEasingCurve(QEasingCurve::OutQuad);

    if (!reverse) {
        animFade->setStartValue(0.0);
        animFade->setEndValue(1.0);
        animMove->setStartValue(pos2);
        animMove->setEndValue(pos1);

    } else {
        emit reverseAnimStarted();
        animFade->setStartValue(1.0);
        animFade->setEndValue(0.0);
        animMove->setStartValue(pos1);
        animMove->setEndValue(pos2);

        connect(animFade, &QPropertyAnimation::finished,
            [this] { QDialog::hide(); });
    }

    animFade->start(QAbstractAnimation::DeleteWhenStopped);
    animMove->start(QAbstractAnimation::DeleteWhenStopped);
}

void UI::viewDialog() {
    auto dialog = new AnimatedDialog{ this };
    dialog->open();

    connect(dialog, &AnimatedDialog::finished,
        [=] {}
    });

}