Live Plotting with PyQtGraph in PyQt4

末鹿安然 提交于 2020-01-13 17:59:50

问题


I am quite new in Python and TRYING to make a PyQt4 app, where I am embedding PyQtGraph in it. I've got this PyQtGraph live plotter that works fantastically:

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_()

For embedding in a bigger PyQt4 app, I need a layout for including a pyqtgraph.PlotWidget(). For that matter I set a centralWidget in my MainWindow. I create a button, that should start plotting just as the previous code does, but just nothing happens when I call the updater function through the plotter function:

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_()

Is nothing happening because I have to thread?


回答1:


There are several things to consider in the code.
First, going in the same direction as @luddek's answer, you need to keep track of your variables. If you define a variable inside a class method and this class method finished executing, the variable is lost. Also it is not visible from the outside.
It is therefore a good idea to use instance variables,
self.plot instead of plot
self.timer instead of timer
self.login_widget instead of login_widget
(also, I would not recomment using global in a PyQt programm, although it is valid code)

Next, PlotWidget does not have a setData method. Plotting the data to the PlotItem's plot is a little more involved:
pg.PlotWidget() has a PlotItem which you can get via .getPlotItem(). Then you need to invoke plot() on it, which returns the actual curve you want to add data to. In the example below I introduced the new variable self.curve to which you can add the data via self.curve.setData(self.data)

Here is the complete working code.

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_()



回答2:


updater() is not called because the timer is removed by the garbage collector.

You need to keep a reference somewhere to the timer. You could for example create the reference in __init__

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


来源:https://stackoverflow.com/questions/41679063/live-plotting-with-pyqtgraph-in-pyqt4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!