PyQt5隐藏部件后如何调整窗口至更小尺寸且不固定大小?
问题:PyQt5中隐藏图表后窗口resize无效,如何动态调整窗口大小?
我正在实现点击按钮隐藏/显示图表的功能,但隐藏图表后调用self.resize()似乎被忽略,窗口无法恢复到之前的小尺寸。用setFixedSize()虽然能生效,但我不想固定窗口尺寸,尝试用setSizePolicy()取消固定也没效果。我的代码如下:
import sys import matplotlib.pyplot as plt from PyQt5.Qt import QSizePolicy from PyQt5.QtWidgets import ( QDialog, QApplication, QGridLayout, QWidget, QGroupBox, QPushButton ) from matplotlib.backends.backend_qt5agg import \ FigureCanvasQTAgg as FigureCanvas class MainWindow(QDialog): def __init__(self): super().__init__() self.layout = QGridLayout() self.setLayout(self.layout) self.settings = QGroupBox('Settings:') self.settingsLayout = QGridLayout() self.settings.setLayout(self.settingsLayout) self.showFigureBtn = QPushButton('Show Figure') self.settingsLayout.addWidget(self.showFigureBtn) self.layout.addWidget(self.settings) self.figureWidget = QWidget() self.figureWidget.setMinimumSize(300, 300) self.figureLayout = QGridLayout(self.figureWidget) self.fig, self.ax = plt.subplots() self.canvas = FigureCanvas(self.fig) self.figureLayout.addWidget(self.canvas) self.figureWidget.setLayout(self.figureLayout) self.layout.addWidget(self.figureWidget) self.figureWidget.setVisible(False) self.showFigureBtn.clicked.connect(self.toggle_figure) self.min_size = (300, 100) self.resize(*self.min_size) def toggle_figure(self): state = not self.figureWidget.isVisible() if state: self.showFigureBtn.setText('Hide Figure') self.min_size = self.size() self.figureWidget.setVisible(state) else: self.showFigureBtn.setText('Show Figure') self.figureWidget.setVisible(state) self.resize(self.min_size) # self.setFixedSize(self.min_size) # self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) if __name__ == '__main__': app = QApplication(sys.argv) GUI = MainWindow() GUI.show() sys.exit(app.exec_())
解决方案
这个问题的核心是Qt的布局管理器会自动调整窗口大小以适应内容,当你隐藏图表组件后,布局会重新计算,但直接调用resize()会被布局的自动调整逻辑覆盖。另外你当前记录min_size的时机也不对——应该在隐藏前保存你想要恢复的尺寸,而不是显示时记录当前窗口大小。
下面是修复后的代码,我标注了关键改动点:
import sys import matplotlib.pyplot as plt from PyQt5.QtWidgets import ( QDialog, QApplication, QGridLayout, QWidget, QGroupBox, QPushButton, QLayout ) from matplotlib.backends.backend_qt5agg import \ FigureCanvasQTAgg as FigureCanvas class MainWindow(QDialog): def __init__(self): super().__init__() # 设置布局的尺寸约束,确保允许窗口缩小到合理尺寸 self.layout = QGridLayout() self.layout.setSizeConstraint(QLayout.SetDefaultConstraint) self.setLayout(self.layout) self.settings = QGroupBox('Settings:') self.settingsLayout = QGridLayout() self.settings.setLayout(self.settingsLayout) self.showFigureBtn = QPushButton('Show Figure') self.settingsLayout.addWidget(self.showFigureBtn) self.layout.addWidget(self.settings) self.figureWidget = QWidget() self.figureWidget.setMinimumSize(300, 300) self.figureLayout = QGridLayout(self.figureWidget) self.fig, self.ax = plt.subplots() self.canvas = FigureCanvas(self.fig) self.figureLayout.addWidget(self.canvas) self.figureWidget.setLayout(self.figureLayout) self.layout.addWidget(self.figureWidget) self.figureWidget.setVisible(False) self.showFigureBtn.clicked.connect(self.toggle_figure) # 初始最小尺寸固定为设置面板的大小 self.min_size = (300, 100) self.resize(*self.min_size) def toggle_figure(self): state = not self.figureWidget.isVisible() if state: self.showFigureBtn.setText('Hide Figure') self.figureWidget.setVisible(state) # 显示图表后让窗口自动适配内容 self.adjustSize() else: self.showFigureBtn.setText('Show Figure') self.figureWidget.setVisible(state) # 先让布局重新计算最小需要的尺寸 self.adjustSize() # 再设置回目标最小尺寸 self.resize(self.min_size) # 允许用户之后自由调整窗口大小 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) if __name__ == '__main__': app = QApplication(sys.argv) GUI = MainWindow() GUI.show() sys.exit(app.exec_())
关键改动说明:
- 布局尺寸约束:给主布局添加
setSizeConstraint(QLayout.SetDefaultConstraint),确保布局允许窗口缩小到内容所需的最小尺寸(默认其实是这个值,但明确设置更稳妥) - 调整时机:显示图表时调用
adjustSize()让窗口自动适配图表+设置面板的大小;隐藏图表时,先调用adjustSize()让布局计算出仅显示设置面板的最小尺寸,再调用resize()设置回你想要的min_size - 修正min_size记录逻辑:不再在显示图表时记录当前尺寸,而是固定初始的最小尺寸(如果你需要动态记录隐藏前的窗口大小,可以在隐藏前添加
self.min_size = self.size()) - 恢复尺寸策略:隐藏后设置
setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding),确保用户之后可以自由调整窗口大小,不会被固定
这样修改后,点击按钮隐藏图表时窗口会正确缩回到你设置的最小尺寸,同时保持窗口可自由调整的特性。
内容的提问来源于stack exchange,提问作者mapf




