Qt实现自动调整尺寸的stackedWidget(PyQt5)

效果预览

PixPin_2026-05-07_10-36-05

代码

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_())
posted @ 2026-05-07 10:37  乌合之众  阅读(21)  评论(0)    收藏  举报
clear