如何为QSplitter中的frame添加显示动画?
解决QSplitter中Frame恢复显示的动画问题
基于Qt Designer创建的示例界面,启动时通过以下代码隐藏frame占用的空间:
QList<int> list = { 0, 400 }; ui.splitter->setSizes(list); ui.frame->setWindowOpacity(0);
需要实现恢复frame占用空间的同时添加动画效果,但尝试以下代码后遇到问题:
尝试的动画实现代码
splitteranimation.h
void SplitterAnimation(QWidget* widget) { int ani_speed = 1000; QPropertyAnimation* geo_ani = new QPropertyAnimation(widget, "geometry"); geo_ani->setDuration(ani_speed); geo_ani->setStartValue(widget->rect()); QRect end = QRect(widget->rect().x(), widget->rect().y(), widget->rect().width() + 200, widget->rect().height()); geo_ani->setEndValue(end); QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(); widget->setGraphicsEffect(eff); QPropertyAnimation *op_eff = new QPropertyAnimation(eff, "opacity"); op_eff->setDuration(ani_speed); op_eff->setStartValue(0); op_eff->setEndValue(1); auto animgroup = new QParallelAnimationGroup; animgroup->addAnimation(geo_ani); animgroup->addAnimation(op_eff); animgroup->start(QAbstractAnimation::DeleteWhenStopped); }
主窗口代码
#include "splitteranimation.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); QList<int> list = { 0, 400 }; ui.splitter->setSizes(list); ui.frame->setWindowOpacity(0); QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this); connect(shortcut, &QShortcut::activated, [=] { qDebug() << "shortcut!"; SplitterAnimation(ui.frame); }); shortcut = new QShortcut(QKeySequence(Qt::Key_F3), this); connect(shortcut, &QShortcut::activated, [this] { qDebug() << "shortcut!"; SplitterAnimation(ui.splitter); }); }
遇到的问题
- 按F2调用针对frame的几何动画:frame自身被调整大小,但QSplitter的布局区域未更新,frame占用的空间仍处于隐藏状态
- 按F3直接对QSplitter调用动画:frame没有被调整大小或显示
解决方案
问题核心是QSplitter的子部件尺寸由sizes属性控制,直接修改子部件的geometry会被QSplitter的布局覆盖,正确的做法是对QSplitter的sizes属性做动画,同时同步处理frame的透明度。
修改后的动画实现
void SplitterAnimation(QSplitter* splitter, QWidget* targetWidget) { int ani_speed = 1000; QList<int> startSizes = splitter->sizes(); // 假设targetWidget是splitter的第一个子部件,目标宽度设为200,第二个部件保持原宽度 QList<int> endSizes = {200, startSizes[1]}; // 1. 针对QSplitter的sizes属性做动画 QPropertyAnimation* splitterAni = new QPropertyAnimation(splitter, "sizes"); splitterAni->setDuration(ani_speed); splitterAni->setStartValue(startSizes); splitterAni->setEndValue(endSizes); // 2. 针对targetWidget的透明度做动画(复用已有效果避免重复创建) QGraphicsOpacityEffect *eff = qobject_cast<QGraphicsOpacityEffect*>(targetWidget->graphicsEffect()); if (!eff) { eff = new QGraphicsOpacityEffect(targetWidget); targetWidget->setGraphicsEffect(eff); } QPropertyAnimation *opacityAni = new QPropertyAnimation(eff, "opacity"); opacityAni->setDuration(ani_speed); opacityAni->setStartValue(0); opacityAni->setEndValue(1); // 并行执行两个动画 auto aniGroup = new QParallelAnimationGroup; aniGroup->addAnimation(splitterAni); aniGroup->addAnimation(opacityAni); aniGroup->start(QAbstractAnimation::DeleteWhenStopped); }
主窗口中调用修改后的函数
// 替换原来的快捷键连接 QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this); connect(shortcut, &QShortcut::activated, [=] { qDebug() << "shortcut!"; SplitterAnimation(ui.splitter, ui.frame); });
关键说明
- QSplitter的子部件尺寸由其
sizes属性管理,直接修改子部件几何属性会被布局重置,必须通过动画修改sizes来调整空间分配 - 透明度动画需要复用已有的
QGraphicsOpacityEffect,避免重复创建导致的资源泄漏 - 并行动画组保证空间展开和淡入效果同步执行
内容的提问来源于stack exchange,提问作者Cesar
相关产品推荐
相关产品推荐

