PyQt5+Matplotlib图表需求:固定Y轴,仅滚动X轴可见区域
解决Y轴固定、仅滚动X轴可见区域的问题
你现在遇到的问题是因为把整个Matplotlib画布放到QGraphicsView里滚动,导致整个绘图区域(包括Y轴)都会跟着移动。要实现Y轴固定、只通过滚动条控制X轴可见范围的效果,我们可以换一种思路:用底部的滚动条直接控制Matplotlib坐标轴的X轴显示范围,而不是滚动整个画布。
下面是修改后的完整代码,关键部分我都加了注释:
from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * import sys from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure import numpy as np class MainWindow(QMainWindow): def __init__(self): super(MainWindow,self).__init__() self.setGeometry(150, 150, 700, 550) # 主部件和布局 central_widget = QWidget() self.setCentralWidget(central_widget) layout = QVBoxLayout(central_widget) layout.setContentsMargins(0,0,0,0) layout.setSpacing(0) # 创建Matplotlib画布和坐标轴 self.figure = Figure(figsize=(8,5), dpi=100) self.canvas = FigureCanvas(self.figure) layout.addWidget(self.canvas) # 调整子图布局,给Y轴留出足够空间 self.figure.subplots_adjust(left=0.1, right=1, bottom=0.1, top=1) self.ax = self.figure.add_subplot(111) # 生成测试数据,X轴范围0-1000 self.total_x_range = [0, 1000] data = np.random.rand(1000) self.ax.plot(data, '-') # 创建底部滚动条 self.scroll_bar = QScrollBar(Qt.Horizontal) layout.addWidget(self.scroll_bar) # 初始化滚动条和X轴可见范围 self.update_scrollbar_range() self.scroll_bar.valueChanged.connect(self.update_x_view) # 监听窗口大小变化,更新滚动条范围 self.resizeEvent = self.on_window_resize def update_scrollbar_range(self): """根据当前窗口宽度计算滚动条的范围""" # 获取画布的像素宽度对应的X轴范围 canvas_width = self.canvas.size().width() # 计算每像素对应的X轴数值(假设DPI固定) pixels_per_x = canvas_width / (self.total_x_range[1] - self.total_x_range[0]) # 可见区域的X轴长度 visible_x_length = self.width() / pixels_per_x # 滚动条的最大值是总X范围减去可见X范围 self.scroll_bar.setRange(0, int(self.total_x_range[1] - visible_x_length)) # 设置滚动条的页面步长(一次滚动的距离) self.scroll_bar.setPageStep(int(visible_x_length)) # 初始显示X轴开头部分 self.ax.set_xlim(self.total_x_range[0], self.total_x_range[0] + visible_x_length) self.canvas.draw() def update_x_view(self, value): """根据滚动条位置更新X轴可见范围""" visible_x_length = self.scroll_bar.pageStep() new_x_min = value new_x_max = new_x_min + visible_x_length self.ax.set_xlim(new_x_min, new_x_max) self.canvas.draw() def on_window_resize(self, event): """窗口大小变化时更新滚动条和X轴范围""" self.update_scrollbar_range() super(MainWindow, self).resizeEvent(event) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() app.exec_()
关键改进点:
- 移除了
QGraphicsView,改用QVBoxLayout将Matplotlib画布和水平滚动条垂直排列,滚动条直接控制X轴的显示范围。 update_scrollbar_range函数会根据窗口宽度计算可见的X轴范围,保证滚动条的范围和页面步长匹配当前窗口尺寸。- 滚动条的
valueChanged信号触发update_x_view函数,动态调整坐标轴的xlim,这样Y轴会始终固定在画布左侧,不会随滚动移动。 - 监听窗口大小变化事件,确保窗口缩放时滚动逻辑依然正常工作。
这样运行后,你拖动底部的滚动条时,只有X轴的可见区域会变化,Y轴的刻度和标签会一直固定在视野左侧。
内容的提问来源于stack exchange,提问作者ignoring_gravity
相关产品推荐
相关产品推荐

