[英]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::Show
和QEvent::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.