我正在尝试使两个绘图具有相同的X可视范围,并且当一个或另一个更改时需要更改。
以下是一些最基本的Python代码,显示了我要做的事情: (只有顶部绘图连接到底部绘图,尝试移动,缩放和缩放)
import numpy as np
import pyqtgraph as pg
from PyQt4 import QtCore, QtGui
class NoiseGenerator():
def __init__(self, signal):
self.signal = signal
def read(self):
y = np.random.rand(512)
self.signal.emit(y)
def close(self):
pass
class AnimationWidget(pg.LayoutWidget):
read_collected = QtCore.pyqtSignal(np.ndarray)
def __init__(self):
super(AnimationWidget, self).__init__()
self.noisePlot_Top = pg.PlotWidget()
self.noisePlot_Top.setLabel('bottom', 'Noise', units='Jigawatts')
self.noiseCurve_Top = pg.PlotCurveItem()
self.noisePlot_Top.addItem(self.noiseCurve_Top)
self.noisePlot_Bot = pg.PlotWidget()
self.noisePlot_Bot.setLabel('bottom', 'Noise', units='Jigawatts')
self.noiseCurve_Bot = pg.PlotCurveItem()
self.noisePlot_Bot.addItem(self.noiseCurve_Bot)
self.layout.addWidget(self.noisePlot_Top)
self.layout.addWidget(self.noisePlot_Bot)
self.noisePlot_Top.sigXRangeChanged.connect(self.updateRegion)
def updateRegion(self):
left,right = self.noiseCurve_Top.getViewBox().viewRange()[0]
self.noiseCurve_Bot.getViewBox().setRange(xRange=(left,right))
def update(self, chunk):
#print "---------"
#print self.averagefft.getViewBox().viewRange()[0]
#print self.averagefft2.getViewBox().viewRange()[0]
#print np.array(self.averagefft.getViewBox().viewRange()[0]) - np.array(self.averagefft2.getViewBox().viewRange()[0])
self.noiseCurve_Top.setData(chunk)
self.noiseCurve_Bot.setData(chunk)
class MainApp():
app = QtGui.QApplication([])
win = QtGui.QMainWindow()
widget = QtGui.QWidget()
win.setCentralWidget(widget)
layout = QtGui.QGridLayout(widget)
win.show()
win.resize(1000,600)
def __init__(self):
w = AnimationWidget()
w.read_collected.connect(w.update)
self.layout.addWidget(w)
noise = NoiseGenerator(w.read_collected)
self.t = QtCore.QTimer()
self.t.timeout.connect(noise.read)
self.t.start(100) #QTimer takes ms
self.app.exec_()
if __name__ == '__main__':
t = MainApp()
每当顶部绘图的范围发生变化时,我会使用以下行更新底部绘图的范围:
def updateRegion(self):
left,right = self.noiseCurve_Top.getViewBox().viewRange()[0]
self.noiseCurve_Bot.getViewBox().setRange(xRange=(left,right))
然而,一旦顶部绘图被更改,底部绘图将不再与顶部的视觉范围完全匹配,并且似乎存在一些偏移。
有没有办法让底部的范围与顶级范围匹配,希望没有任何偏移?
感谢。
[更新]
我很好奇这个问题是否与时间有关(在XRangeChanged事件触发之后)所以我移动了代码行以尝试在每次更新绘图时更新viewBox范围并且仍然获得相同的偏移量。所以我确信它与我检索和设置范围值的方式有关。
[解决]
正如three_pineapples所建议的那样,我并不知道setLink方法的存在,这使得完成这项任务非常简单。
import numpy as np
import pyqtgraph as pg
from PyQt4 import QtCore, QtGui
class NoiseGenerator():
def __init__(self, signal):
self.signal = signal
def read(self):
y = np.random.rand(512)
self.signal.emit(y)
def close(self):
pass
class AnimationWidget(pg.LayoutWidget):
read_collected = QtCore.pyqtSignal(np.ndarray)
def __init__(self):
super(AnimationWidget, self).__init__()
self.noisePlot_Top = pg.PlotWidget()
self.noisePlot_Top.setLabel('bottom', 'Noise', units='Jigawatts')
self.noiseCurve_Top = pg.PlotCurveItem()
self.noisePlot_Top.addItem(self.noiseCurve_Top)
self.noisePlot_Bot = pg.PlotWidget()
self.noisePlot_Bot.setLabel('bottom', 'Noise', units='Jigawatts')
self.noiseCurve_Bot = pg.PlotCurveItem()
self.noisePlot_Bot.addItem(self.noiseCurve_Bot)
self.layout.addWidget(self.noisePlot_Top)
self.layout.addWidget(self.noisePlot_Bot)
self.noisePlot_Top.getViewBox().setXLink(self.noisePlot_Bot) #Link the two plot's X ranges
def update(self, chunk):
self.noiseCurve_Top.setData(chunk)
self.noiseCurve_Bot.setData(chunk)
class MainApp():
app = QtGui.QApplication([])
win = QtGui.QMainWindow()
widget = QtGui.QWidget()
win.setCentralWidget(widget)
layout = QtGui.QGridLayout(widget)
win.show()
win.resize(1000,600)
def __init__(self):
w = AnimationWidget()
w.read_collected.connect(w.update)
self.layout.addWidget(w)
noise = NoiseGenerator(w.read_collected)
self.t = QtCore.QTimer()
self.t.timeout.connect(noise.read)
self.t.start(100) #QTimer takes ms
self.app.exec_()
if __name__ == '__main__':
t = MainApp()
注意: 根据您链接两个图的顺序,如果您以编程方式更改绘图的数据或其范围,它可能具有一定的意义 - 我只需翻转项目即可解决一个小问题:
# Can be
self.noisePlot_Top.getViewBox().setXLink(self.noisePlot_Bot)
# - or -
self.noisePlot_Bot.getViewBox().setXLink(self.noisePlot_Top)
# But not both