使用PyQtGraph在PyQt4中实时绘图

5

我在Python方面还是个新手,正试图制作一个PyQt4应用程序,在其中嵌入了PyQtGraph。我有一个非常棒的PyQtGraph实时绘图仪,它能够很好地工作:

from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import random

app = QtGui.QApplication([])
p = pg.plot()
curve = p.plot()
data = [0]

def updater():

    data.append(random.random())
    curve.setData(data) #xdata is not necessary


timer = QtCore.QTimer()
timer.timeout.connect(updater)
timer.start(0)

if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

为了嵌入到更大的PyQt4应用程序中,我需要一个布局来包含pyqtgraph.PlotWidget()。为此,我在我的MainWindow中设置了一个centralWidget。我创建了一个按钮,当我通过plotter函数调用updater函数时,它应该开始绘图,但是什么也没有发生:

import sys
from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.central_widget = QtGui.QStackedWidget()
        self.setCentralWidget(self.central_widget)
        login_widget = LoginWidget(self)#to say where the button is
        login_widget.button.clicked.connect(self.plotter)
        self.central_widget.addWidget(login_widget)

    def plotter(self):
        self.data =[0]
        timer = QtCore.QTimer()
        timer.timeout.connect(self.updater)
        timer.start(0)

    def updater(self):

        self.data.append(random.random())
        plot.setData(self.data)

class LoginWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        global plot
        super(LoginWidget, self).__init__(parent)
        layout = QtGui.QHBoxLayout()
        self.button = QtGui.QPushButton('Start Plotting')
        layout.addWidget(self.button)
        plot = pg.PlotWidget()
        layout.addWidget(plot)
        self.setLayout(layout)

if __name__ == '__main__':
    app = QtGui.QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()

因为我需要使用线程,所以什么都没有发生吗?

2个回答

4
在代码中有几个需要考虑的事情。首先,与@luddek的回答方向相同,您需要跟踪变量。如果您在类方法中定义一个变量,并且该类方法执行完成,则该变量将丢失。此外,它在外部不可见。因此,使用实例变量是一个好主意,例如:self.plot代替plotself.timer代替timerself.login_widget代替login_widget。(另外,在PyQt程序中我不建议使用global,尽管它是有效的代码)。
其次,PlotWidget没有setData方法。将数据绘制到PlotItem的图表上需要更多的操作:通过.getPlotItem()获取pg.PlotWidget()PlotItem。然后,您需要在其上调用plot(),它会返回您想要添加数据的实际曲线。在下面的示例中,我引入了新变量self.curve,您可以通过self.curve.setData(self.data)向其添加数据。
以下是完整的工作代码。
from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.central_widget = QtGui.QStackedWidget()
        self.setCentralWidget(self.central_widget)
        self.login_widget = LoginWidget(self)
        self.login_widget.button.clicked.connect(self.plotter)
        self.central_widget.addWidget(self.login_widget)

    def plotter(self):
        self.data =[0]
        self.curve = self.login_widget.plot.getPlotItem().plot()

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updater)
        self.timer.start(0)

    def updater(self):

        self.data.append(self.data[-1]+0.2*(0.5-random.random()) )
        self.curve.setData(self.data)

class LoginWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(LoginWidget, self).__init__(parent)
        layout = QtGui.QHBoxLayout()
        self.button = QtGui.QPushButton('Start Plotting')
        layout.addWidget(self.button)
        self.plot = pg.PlotWidget()
        layout.addWidget(self.plot)
        self.setLayout(layout)

if __name__ == '__main__':
    app = QtGui.QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()

非常感谢@ImportanceOfBeingErnest,我真的在努力理解变量作用域,但这需要一些时间。幸运的是你们都是热情的程序员 :-) 另外我在文档中没有找到正确使用pg.PlotWidget()的方法.....再次感谢! - Ivy
1
如果这个解决了你的问题,请考虑接受它。如果没有,请随时相应地完善你的问题。 - ImportanceOfBeingErnest

2

updater() 没有被调用,因为计时器被垃圾回收器移除了。

你需要在某个地方保留计时器的引用。例如,你可以在 __init__ 中创建该引用。

def __init__(self, parent=None):
    ...
    self.timer = QtCore.QTimer()

1
虽然这是正确的,但防止计时器被垃圾回收只是整个问题的一部分。 - ImportanceOfBeingErnest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接