You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:32:37