PyQtGraph,使两个图匹配每个视觉范围(产生偏移)?

时间:2016-11-05 10:45:05

标签: python range offset pyqtgraph

我正在尝试使两个绘图具有相同的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))

然而,一旦顶部绘图被更改,底部绘图将不再与顶部的视觉范围完全匹配,并且似乎存在一些偏移。

Range Not Equal

有没有办法让底部的范围与顶级范围匹配,希望没有任何偏移?

感谢。

[更新]

我很好奇这个问题是否与时间有关(在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()

Range Now Equal

注意: 根据您链接两个图的顺序,如果您以编程方式更改绘图的数据或其范围,它可能具有一定的意义 - 我只需翻转项目即可解决一个小问题:

# Can be
self.noisePlot_Top.getViewBox().setXLink(self.noisePlot_Bot)
# - or -
self.noisePlot_Bot.getViewBox().setXLink(self.noisePlot_Top)
# But not both

0 个答案:

没有答案