PyQt6中嵌入pyqtgraph的GraphicsLayoutWidget时QScrollArea滚动条不显示
问题:PyQt6中QScrollArea嵌入pyqtgraph GraphicsLayoutWidget后滚动条不显示
尝试在PyQt6的QScrollArea中嵌入pyqtgraph的GraphicsLayoutWidget,让滚动条正常显示。试过修改布局、重新分配GraphicsLayoutWidget、设置默认最小尺寸和调用show()函数,问题仍未解决。
问题核心代码
def update_graphs(self): self.graphWidget.clear() self.graph_data = pd.concat([self.data[(self.data['time'] > (comment - self.time_before)) & (self.data['time'] < (comment + self.time_after))] for comment in self.selected_comments['time']]) self.graph_dict = dict.fromkeys(self.graph_data.columns.values[:-1], None) time = (self.graph_data['time'].dt.tz_localize(None) - pd.Timestamp("1970-01-01") + pd.Timedelta('5h')) / pd.Timedelta('1s') for i, trace in enumerate(self.graph_dict.keys()): self.graph_dict[trace] = self.graphWidget.addPlot(row=i, col=0, name=trace, title=trace ) self.graph_dict[trace].setMinimumHeight(150) self.graph_dict[trace].addItem(pg.PlotCurveItem(clear=True, pen='g', x=time.values, y=self.graph_data[trace].values), row=i, col=0) self.graph_dict[trace].setXLink(list(self.graph_dict.keys())[0]) y_axis = pg.AxisItem(orientation='left', text='Voltage', units='V', unitPrefix='m') y_axis.setLabel(text='Voltage', units='V') y_axis.setScale(1e-3) self.graph_dict[trace].setAxisItems({'bottom': pg.DateAxisItem(orientation='bottom'), 'left': y_axis}) if not i == len(self.graph_dict) - 1: self.graph_dict[trace].hideAxis('bottom') self.scrollArea.show()
Qt Designer生成的相关代码
self.scrollArea = QtWidgets.QScrollArea(parent=self.graphTab) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth()) self.scrollArea.setSizePolicy(sizePolicy) self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.scrollArea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.SizeAdjustPolicy.AdjustIgnored) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.graphWidget = GraphicsLayoutWidget() self.graphWidget.setGeometry(QtCore.QRect(0, 0, 1043, 655)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.graphWidget.sizePolicy().hasHeightForWidth()) self.graphWidget.setSizePolicy(sizePolicy) self.graphWidget.setObjectName("graphWidget") self.scrollArea.setWidget(self.graphWidget)
解决方案
关键问题分析
QScrollArea显示滚动条的前提是内部widget的尺寸超过了scrollArea的可视区域,当前代码存在两个核心问题:
GraphicsLayoutWidget被设置了固定初始尺寸,添加多个Plot后无法自动更新自身总尺寸以容纳所有内容;- 仅给单个Plot设置最小高度,但未同步更新
GraphicsLayoutWidget的整体最小尺寸,导致scrollArea无法感知内容溢出。
修复步骤
- 移除固定初始尺寸:删掉
self.graphWidget.setGeometry(QtCore.QRect(0, 0, 1043, 655)),让GraphicsLayoutWidget根据内容自动计算尺寸; - 调整scrollArea的尺寸适配策略:将
SizeAdjustPolicy从AdjustIgnored改为AdjustToContents,确保scrollArea能根据内部widget尺寸调整滚动逻辑; - 强制更新GraphicsLayoutWidget的最小高度:添加完所有Plot后,根据Plot数量计算总最小高度并设置,触发scrollArea的滚动条逻辑。
修改后的代码
调整Qt Designer生成的代码
self.scrollArea = QtWidgets.QScrollArea(parent=self.graphTab) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth()) self.scrollArea.setSizePolicy(sizePolicy) self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded) # 修改尺寸适配策略 self.scrollArea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.SizeAdjustPolicy.AdjustToContents) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.graphWidget = GraphicsLayoutWidget() # 移除固定尺寸设置 sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.graphWidget.sizePolicy().hasHeightForWidth()) self.graphWidget.setSizePolicy(sizePolicy) self.graphWidget.setObjectName("graphWidget") self.scrollArea.setWidget(self.graphWidget)
修改update_graphs方法
在方法末尾添加尺寸更新逻辑:
def update_graphs(self): self.graphWidget.clear() self.graph_data = pd.concat([self.data[(self.data['time'] > (comment - self.time_before)) & (self.data['time'] < (comment + self.time_after))] for comment in self.selected_comments['time']]) self.graph_dict = dict.fromkeys(self.graph_data.columns.values[:-1], None) time = (self.graph_data['time'].dt.tz_localize(None) - pd.Timestamp("1970-01-01") + pd.Timedelta('5h')) / pd.Timedelta('1s') plot_count = len(self.graph_dict.keys()) for i, trace in enumerate(self.graph_dict.keys()): self.graph_dict[trace] = self.graphWidget.addPlot(row=i, col=0, name=trace, title=trace ) self.graph_dict[trace].setMinimumHeight(150) self.graph_dict[trace].addItem(pg.PlotCurveItem(clear=True, pen='g', x=time.values, y=self.graph_data[trace].values), row=i, col=0) self.graph_dict[trace].setXLink(list(self.graph_dict.keys())[0]) y_axis = pg.AxisItem(orientation='left', text='Voltage', units='V', unitPrefix='m') y_axis.setLabel(text='Voltage', units='V') y_axis.setScale(1e-3) self.graph_dict[trace].setAxisItems({'bottom': pg.DateAxisItem(orientation='bottom'), 'left': y_axis}) if not i == plot_count - 1: self.graph_dict[trace].hideAxis('bottom') # 计算并设置graphWidget的总最小高度 total_min_height = plot_count * 150 self.graphWidget.setMinimumHeight(total_min_height) # 强制更新布局,确保尺寸生效 self.graphWidget.updateGeometry() self.scrollArea.show()
额外说明
- 保持
setWidgetResizable(True)不变,该属性让scrollArea自动适配内部widget的宽度,仅在高度方向触发滚动; - 若需要更精确的尺寸计算,可通过获取每个Plot的实际高度求和,替代固定的
150*plot_count。
内容的提问来源于stack exchange,提问作者Lukas
相关产品推荐
相关产品推荐

