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

PyQtGraph双绘图组件X轴同步偏差及setLimits等方法无效咨询

解决PyQtGraph双图X轴同步偏差问题

嘿,我来帮你捋捋这个X轴偏差的问题~ 你现在遇到的核心问题不是setLimits或setXRange的用法不对,而是两个绘图组件的X轴数据本身就没有对齐!咱们一步步拆解:

问题根源分析

看你的代码细节:

  • CandlestickItem绘制K线时,用的是自增的index(0、1、2...)作为X坐标,相当于K线是基于连续索引排列的;
  • 而plot2直接用list(self.xdict.keys())作为X轴数据,这是你实际业务中的时间对应数值(比如时间戳或自定义时间key)。

这两个X轴的数值范围完全不匹配,所以哪怕给两个plot设置相同的setXRange(-1,50),显示内容也不可能对齐——plot1显示前51个K线,plot2显示key值在-1到50之间的y数据,自然会出现偏差。

解决方案

1. 让K线组件使用实际X轴数值

修改CandlestickItem的generatePicture方法,把绘图的X坐标从自增index换成数据里的time字段(和plot2一致的xdict key值),同时适配K线宽度:

class CandlestickItem(pg.GraphicsObject): 
    def __init__(self, data): 
        pg.GraphicsObject.__init__(self) 
        self.data = data ## data must have fields: time, open, close, min, max 
        self.generatePicture() 

    def generatePicture(self): 
        self.picture = QtGui.QPicture() 
        p = QtGui.QPainter(self.picture) 
        p.setPen(pg.mkPen('k')) 

        # 计算K线宽度:用相邻时间点的间隔除以3(避免K线重叠)
        w = 1 / 3.
        if len(self.data) > 1:
            w = (self.data[1][0] - self.data[0][0]) / 3.

        # 注意:max、min是Python内置函数,别用做变量名,改成max_val、min_val
        for (t, close, max_val, min_val, open_val) in self.data: 
            if open_val > close: 
                p.setBrush(pg.mkBrush('r')) 
                p.setPen(pg.mkPen('r')) 
            else: 
                p.setBrush(pg.mkBrush('g')) 
                p.setPen(pg.mkPen('g')) 

            # 用实际的time值t作为X坐标,替代原来的index
            p.drawLine(QtCore.QPointF(t, min_val), QtCore.QPointF(t, max_val)) 
            p.drawRect(QtCore.QRectF(t - w, open_val, w*2, close - open_val)) 

        p.end() 

    def paint(self, p, *args): 
        p.drawPicture(0, 0, self.picture) 

    def boundingRect(self): 
        return QtCore.QRectF(self.picture.boundingRect()) 

2. 用X轴链接实现自动同步

PyQtGraph提供了更省心的X轴同步方式——setXLink,只要把两个plot的X轴链接起来,拖动、缩放其中一个时,另一个会自动同步范围,不用手动反复设置setXRange:

# 创建时间轴(可以复用,也可分别创建,只要xdict一致即可)
date_axis = TimeAxisItem(self.xdict, orientation='bottom')

# 初始化第一个plot
self.plot1 = pg.PlotWidget(axisItems={'bottom': date_axis})
# 基于实际xdict key值设置初始范围(留一点边距更美观)
min_x = min(self.xdict.keys())
max_x = max(self.xdict.keys())
margin = (max_x - min_x) * 0.05
self.plot1.setXRange(min_x - margin, max_x + margin)
self.plot1.setLimits(xMin=min_x - margin*4, xMax=max_x + margin*4)

# 添加K线组件
item = CandlestickItem(data)
self.plot1.addItem(item)

# 初始化第二个plot,链接X轴到plot1
self.plot2 = pg.PlotWidget(axisItems={'bottom': TimeAxisItem(self.xdict, orientation='bottom')})
self.plot2.setXLink(self.plot1)  # 关键:这一行实现X轴自动同步
self.plot2.plot(list(self.xdict.keys()), y)

额外小提示

你的TimeAxisItem里vs = int(v * scale)可能会导致时间字符串匹配出错,建议后续可以用bisect模块取最接近的key值优化,但这不是X轴偏差的核心问题,先解决对齐后再调整即可。

这样修改后,两个plot的X轴就会完全对齐,同步缩放拖动也没问题啦~

内容的提问来源于stack exchange,提问作者shadow dk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:08:04