qwidget上的动画无效

时间:2015-08-10 12:33:12

标签: c++ qt

我想要一个小部件在显示/隐藏时为其不透明度设置动画。我使用下面的代码,但它不起作用。

如果我为属性“maximumHeight”设置动画,则会在show()中设置动画,但不会在hide()中设置动画。有人能告诉我哪里出错了吗?

标题文件
byeform.h

#include <QWidget>
#include <QPropertyAnimation>

namespace Ui {
class ByeForm;
}

class ByeForm : public QWidget
{
    Q_OBJECT

public:
    explicit ByeForm(QWidget *parent = 0);
    ~ByeForm();

private:
    Ui::ByeForm *ui;

    QPropertyAnimation *mpTransition;

protected:
    bool eventFilter(QObject *obj, QEvent *event);
};

源文件
byeform.cpp

#include "byeform.h"
#include "ui_byeform.h"
#include <QDebug>

ByeForm::ByeForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ByeForm)
{
    ui->setupUi(this);

    this->installEventFilter(this);

    mpTransition = new QPropertyAnimation(this, "windowOpacity");
    mpTransition->setDuration(1000);
    mpTransition->setStartValue(0.00);
    mpTransition->setEndValue(1.00);
}

ByeForm::~ByeForm()
{
    delete ui;
}

bool ByeForm::eventFilter(QObject *obj, QEvent *event)
{
    if (this == obj && QEvent::Show == event->type())
    {
        qDebug() << Q_FUNC_INFO << "in show";
        mpTransition->setDirection(QAbstractAnimation::Forward);
        mpTransition->start();
    }
    else if (this == obj && (QEvent::Hide == event->type() ||
                             QEvent::Close == event->type()))
    {
        mpTransition->setDirection(QAbstractAnimation::Backward);
        mpTransition->start();
    }

    return false;
}

2 个答案:

答案 0 :(得分:0)

这可以解决吗?

bool ByeForm::eventFilter(QObject *obj, QEvent *event)
{
    if (this == obj && QEvent::Show == event->type())
    {
        qDebug() << Q_FUNC_INFO << "in show";
        mpTransition->setDirection(QAbstractAnimation::Forward);
        mpTransition->start();
        return true; // you might want to remove this line
    }
    else if (this == obj && (QEvent::Hide == event->type() ||
                             QEvent::Close == event->type()))
    {
        mpTransition->setDirection(QAbstractAnimation::Backward);
        mpTransition->start();
        return true; // you might want to remove this line
    }

    return QWidget::eventFilter(obj, event);
}

当然,它不起作用,因为它在您开始动画时已经隐藏了。在动画结束之前,您需要延长可见性。

像这样,也许:

void ByeForm::setVisible(bool visible)
{
    if(isVisible() && !visible) // transition to hide
    {
        // m_bHideCalled = true;

        mpTransition->setDirection(QAbstractAnimation::Backward);
        mpTransition->start();
        QTimer::singleShot(1000, this, SLOT(hide());
    }
    if(!isVisible() && visible) // transition to show
    {
        mpTransition->setDirection(QAbstractAnimation::Forward);
        mpTransition->start();
    show();
    }
//    if(m_bHideCalled)
//    {
//        m_bHideCalled = false;
//        hide();
//    }
}

请注意,您可能需要m_bHideCalled。在构造函数中将其设置为false。这个名字可能会更好。

答案 1 :(得分:0)

它有效,但我认为这不是一个很好的方法(我认为你应该在关闭事件发生前做动画)

bool ByeForm::eventFilter(QObject *obj, QEvent *event)
{
    if (this == obj && QEvent::Show == event->type())
    {
        qDebug() << Q_FUNC_INFO << "in show";
        mpTransition->setDirection(QAbstractAnimation::Forward);
        mpTransition->start();
    }
    else if (this == obj && (QEvent::Hide == event->type() ||
                             QEvent::Close == event->type()))
    {
        mpTransition->setDirection(QAbstractAnimation::Backward);
        mpTransition->start();

        while (mpTransition->state() == QAbstractAnimation::Running)
        {
            QApplication::processEvents();
        }
    }

    return false;
}

其他方法

你也可以像这样覆盖closeEvent方法:

void MainWindow::closeEvent(QCloseEvent* e)
{
    mpTransition->setDirection(QAbstractAnimation::Backward);
    mpTransition->start();
    e->ignore();
}

但是在这种情况下你应该在animate完成后做一些事情(例如连接信号finished并调用一些方法来关闭窗口/应用程序/等)。 您也应该检查,手动调用关闭事件或用户操作。