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
相关产品推荐
相关产品推荐

