效果预览

代码
import sys
from PyQt5.QtWidgets import (
QApplication, QLineEdit, QMainWindow, QSizePolicy, QWidget, QVBoxLayout,
QPushButton, QStackedWidget, QLabel, QFrame
)
from PyQt5.QtCore import QPropertyAnimation, QEasingCurve, QSize
class AutoSizeStackedWidget(QStackedWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.currentChanged.connect(self.animate_height)
self.animation = QPropertyAnimation(self, b"minimumHeight")
self.animation.setDuration(300) # 动画时长 300 毫秒
self.animation.setEasingCurve(QEasingCurve.InOutQuad) # 平滑曲线
def animate_height(self, index):
# 获取新页面的理想高度
new_height = self.widget(index).sizeHint().height()
# 停止当前正在进行的动画
self.animation.stop()
# 设置动画的起始值和终点值
self.animation.setStartValue(self.height())
self.animation.setEndValue(new_height)
self.animation.start()
self.on_page_changed(index)
def on_page_changed(self, index):
# 遍历所有页面,将非当前页设为 Ignored,当前页设为 Preferred
for i in range(self.count()):
widget = self.widget(i)
if i == index:
widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
else:
widget.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
# 强制布局刷新
self.adjustSize()
class DemoWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("平滑缩放的 StackedWidget")
self.resize(400, 300)
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
# 实例化自定义的动画 StackedWidget
self.stack = AutoSizeStackedWidget()
# 页面 1:内容较少
self.page1 = QLineEdit("这是第一页\n内容很少,高度较低")
# self.page1 = QFrame()
# p1_layout = QVBoxLayout(self.page1)
# p1_layout.addWidget(QLabel("这是第一页\n内容很少,高度较低"))
# self.page1.setStyleSheet("background-color: #f0f0f0; border: 1px solid #ccc;")
# 页面 2:内容很多
self.page2 = QFrame()
p2_layout = QVBoxLayout(self.page2)
for i in range(8):
p2_layout.addWidget(QLabel(f"这是第二页的第 {i+1} 行内容..."))
self.page2.setStyleSheet("background-color: #e1f5fe; border: 1px solid #03a9f4;")
self.stack.addWidget(self.page1)
self.stack.addWidget(self.page2)
# 切换按钮
self.btn_switch = QPushButton("切换页面")
self.btn_switch.clicked.connect(self.switch_page)
layout.addWidget(self.btn_switch)
layout.addWidget(self.stack)
layout.addStretch() # 底部留白,观察高度变化
def switch_page(self):
new_index = 1 if self.stack.currentIndex() == 0 else 0
self.stack.setCurrentIndex(new_index)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = DemoWindow()
window.show()
sys.exit(app.exec_())