Живой график с PyQtGraph в PyQt4

Я новичок в 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(). В этом отношении я установил CentralWidget в моем MainWindow. Я создаю кнопку, которая должна начать рисовать так же, как и предыдущий код, но ничего не происходит, когда я вызываю функцию обновления через функцию плоттера:

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

Ничего не происходит, потому что я должен нить?


person Ivy    schedule 16.01.2017    source источник


Ответы (2)


В коде нужно учитывать несколько моментов.
Во-первых, если идти в том же направлении, что и ответ @luddek, вам нужно отслеживать свои переменные. Если вы определяете переменную внутри метода класса, и этот метод класса завершает выполнение, переменная теряется. Кроме того, он не виден снаружи.
Поэтому рекомендуется использовать переменные экземпляра,
self.plot вместо plot
self.timer вместо timer
self.login_widget вместо login_widget
(также, Я бы не рекомендовал использовать global в программе PyQt, хотя это допустимый код)

Далее, у PlotWidget нет метода setData. Нанесение данных на график PlotItem немного сложнее:
pg.PlotWidget() имеет PlotItem, который вы можете получить через .getPlotItem(). Затем вам нужно вызвать на нем 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_()
person ImportanceOfBeingErnest    schedule 17.01.2017
comment
Большое спасибо @ImportanceOfBeingErnest, я действительно пытаюсь наладить понимание области переменных, но это требует времени. К счастью, вы, ребята, страстные программисты :-) Также я не нашел правильного использования pg.PlotWidget() в документации.....Еще раз спасибо! - person Ivy; 17.01.2017
comment
Если это решило вашу проблему, рассмотрите возможность принять его. Если нет, не стесняйтесь уточнить свой вопрос соответственно. - person ImportanceOfBeingErnest; 17.01.2017

updater() не вызывается, потому что таймер удаляется сборщиком мусора.

Вам нужно где-то сохранить ссылку на таймер. Например, вы можете создать ссылку в __init__

def __init__(self, parent=None):
    ...
    self.timer = QtCore.QTimer()
person luddek    schedule 16.01.2017
comment
Хотя это правильно, предотвращение сборки мусора таймера — это только часть всей проблемы. - person ImportanceOfBeingErnest; 17.01.2017