You need to enable JavaScript to run this app. 如何实现QFrame点击伸缩时内部指定布局不发生垂直尺寸调整?
优惠活动
大模型
产品
解决方案
定价
更多

如何实现QFrame点击伸缩时内部指定布局不发生垂直尺寸调整?

问题根因

  • 没有维护展开/收缩的状态标记,点击后只会单向缩小不会回弹
  • 直接修改QFrame的geometry会被内部布局的尺寸策略覆盖,动画过程会出现布局抖动
  • 内容区域的显隐没有和动画联动,收缩到头部高度后内容还会被布局强行撑开

修复后的实现代码

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(400, 800)
        # 维护展开状态标记
        self.is_expanded = True

        self.frame = QFrame()
        self.frame.setStyleSheet("background: green; border-radius: 8px;")
        # 给frame设置尺寸策略,水平可以扩展,垂直根据内容适配
        self.frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        self.frame_layout = QVBoxLayout()
        self.frame_layout.setContentsMargins(0,0,0,0)
        self.frame_layout.setSpacing(0)
        self.frame.setLayout(self.frame_layout)

        self.header_layout = QHBoxLayout()
        self.header_label = QLabel("Marvin sollte Programmieren lernen!")
        # 给头部设置固定高度,收缩后frame高度就是头部高度
        self.header_label.setFixedHeight(40)
        self.header_layout.addWidget(self.header_label)

        self.content_layout = QVBoxLayout()
        self.content_frame = QFrame()
        self.content_frame.setStyleSheet("background: red; border-radius: 8px;")
        # 内容垂直固定高度,水平自适应
        self.content_frame.setFixedHeight(500)
        self.content_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.content_layout.addWidget(self.content_frame)

        self.frame_layout.addLayout(self.header_layout)
        self.frame_layout.addLayout(self.content_layout)

        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(self.frame)
        # 底部加 stretch 保证frame永远靠顶部
        self.main_layout.addStretch()
        self.setLayout(self.main_layout)

        self.frame.mouseReleaseEvent = lambda _:self.toggle_frame()

    def toggle_frame(self):
        current_height = self.frame.height()
        # 收缩后的高度就是头部的高度
        header_height = self.header_label.height()
        # 展开后的高度是头部+内容高度
        expanded_height = header_height + self.content_frame.height()

        self.animation = QPropertyAnimation(self.frame, b"maximumHeight")
        self.animation.setDuration(500)
        self.animation.setStartValue(current_height)
        if self.is_expanded:
            # 收缩到头部高度
            self.animation.setEndValue(header_height)
        else:
            # 展开到完整高度
            self.animation.setEndValue(expanded_height)
        self.animation.setEasingCurve(QEasingCurve.OutCubic)
        self.animation.start()
        # 切换状态
        self.is_expanded = not self.is_expanded

if __name__ == "__main__":
    app = QApplication([])
    demo = AppDemo()
    demo.show()
    app.exec_()

关键修改说明

  • 新增is_expanded状态标记,点击时切换展开/收缩两个状态,支持反复点击交互
  • 改用maximumHeight作为动画属性,避免布局对frame尺寸的强制约束,动画过程无抖动更流畅
  • 明确设置各组件的尺寸策略:内容区域水平自适应、垂直固定高度,完全符合需求
  • 布局的边距和间距设为0,避免展开收缩时出现多余的空白间隙
  • 主布局底部增加拉伸项,保证frame始终停靠在容器顶部,交互效果符合预期

内容的提问来源于stack exchange,提问作者Mergen Studios

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 01:48:03