QWidget添加滚动条失效且绘图被压缩的问题求助
问题解决:QWidget中滚动视图失效与绘图压缩问题
核心问题分析
- 绘图被压缩:Matplotlib画布(MplCanvas)的尺寸策略未正确配置,导致布局强制压缩其显示大小
- 滚动条不工作:重复添加绘图部件导致布局内容混乱,且画布未保留足够高度触发滚动逻辑
修复步骤及代码修改
1. 修复MplCanvas的尺寸策略
取消注释尺寸策略设置,并调整为Preferred,确保画布保持预设宽高,避免被压缩:
canvas.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
同时建议在MplCanvas类中明确设置最小尺寸,确保布局不会过度压缩:
class MplCanvas(FigureCanvas): def __init__(self, parent=None, width=5, height=5, dpi=300, ...): super().__init__(Figure(figsize=(width, height), dpi=dpi)) self.setParent(parent) # 强制设置最小尺寸 self.setMinimumSize(self.figure.get_figwidth()*self.figure.dpi, self.figure.get_figheight()*self.figure.dpi)
2. 清空旧绘图,避免重复添加
在init_plot方法开头移除已有绘图部件(保留标题),防止重复添加导致布局溢出:
def init_plot(self): # 移除标题之外的所有旧部件 while self.vbox.count() > 1: item = self.vbox.takeAt(1) widget = item.widget() if widget: widget.deleteLater() # 原有绘图逻辑 for energy, label in zip(self.IRC_File[0, :].reshape(1, -1), self.Param_File[0, 1]): for i, (param, lab) in enumerate(zip(self.IRC_File[1:, :], self.Param_File[1:,0])): canvas = MplCanvas(self, width=5, height=5, dpi=300, x=param, y=energy, x_label=lab, y_label=label) canvas.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) self.vbox.addWidget(canvas)
3. 优化滚动区域配置
确保滚动区域占满父布局空间,添加尺寸策略设置:
self.scrolls.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
修改后的完整代码
class PlottingPage(QtWidgets.QWidget): def __init__(self, parent=None, data=None): super().__init__(parent) self.parent = parent self.data = data self.scrolls = QtWidgets.QScrollArea() self.scrolls.setWidgetResizable(True) # 设置滚动区域尺寸策略,占满可用空间 self.scrolls.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.widget = QtWidgets.QWidget() self.vbox = QtWidgets.QVBoxLayout(self.widget) self.scrolls.setWidget(self.widget) self.title = QtWidgets.QLabel("Plots", alignment=QtCore.Qt.AlignTop) self.vbox.addWidget(self.title) main_layout = QtWidgets.QVBoxLayout(self) main_layout.addWidget(self.scrolls) if self.data: self.IRC_File = data[0] self.Param_File = data[1] def init_plot(self): # 清空旧绘图部件 while self.vbox.count() > 1: item = self.vbox.takeAt(1) widget = item.widget() if widget: widget.deleteLater() for energy, label in zip(self.IRC_File[0, :].reshape(1, -1), self.Param_File[0, 1]): for i, (param, lab) in enumerate(zip(self.IRC_File[1:, :], self.Param_File[1:,0])): canvas = MplCanvas(self, width=5, height=5, dpi=300, x=param, y=energy, x_label=lab, y_label=label) canvas.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) self.vbox.addWidget(canvas) def update_data(self, data): self.IRC_File = data[0] self.Param_File = data[1] self.init_plot()
额外说明
- 如果MplCanvas的
sizeHint()未正确返回预设尺寸,可手动重写该方法:def sizeHint(self): return QtCore.QSize(self.figure.get_figwidth()*self.figure.dpi, self.figure.get_figheight()*self.figure.dpi) - 滚动条仅在内容总高度超过滚动区域高度时显示,确保绘图数量或单图高度足够触发滚动。
内容的提问来源于stack exchange,提问作者Hamza
相关产品推荐
相关产品推荐

