You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 03:10:16