Live Plotting with PyQtGraph in PyQt4 #2

2019-07-26 04:42发布

First of all sorry for the lenght. I want to explain my problem as good as possible. I am quite new to Python and trying to make a plotting app using PyQtGraph embedded in PyQt4. Some days ago I got a really nice answer to my plotting problem, and my next step is to have two PyQtGraphs plot Widgets simoultaneously plotting in the same PyQt4's CentralWidget. By the same approach as in the link described, both plots work fine, but the GUI gets unresponsive. For overcoming this, I am aiming to use QThread, and for that, I need to have my plotting functions in different classes. But I am messing with my variables, and can't see how:

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(Plots.plotter)
        self.central_widget.addWidget(self.login_widget)


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)


class Plots(MainWindow):

    def print(self):
        print('hello World')

    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)

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

That gives me an error at Plots.plotter:

self.data = [0]
AttributeError: 'bool' object has no attribute 'data'

If in the MainWindow class I substitute the 'button.connect' argument with Plots.print, it works fine. So I can see there is something wrong with the fact that I make an LoginWidget object in MainWindow, and then Plots inherits from MainWindow, calling that same LoginWidget object again.

I have tried a proposed solution where the father (MainWindow) does not access the methods of the children (Plots). But if, from Plots, I want to call the class where I aim placing my thread in, I get the same error again....

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


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)


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.central_widget.addWidget(self.login_widget)


class Plots(MainWindow):
    def __init__(self, parent=None):
        super(Plots, self).__init__(parent=parent)
        self.login_widget.button.clicked.connect(MyThread.plotter)



class MyThread(MainWindow):
    def __init__(self, parent=None):
        super(Aname, self).__init__(parent=parent)

    def print(self):
        print('hello World')

    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)


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    w = Plots()
    w.show()
    sys.exit(app.exec_())

1条回答
走好不送
2楼-- · 2019-07-26 05:07

In inheritance the father should not access the methods of the children, It is better to inherit and implement new methods that have nothing to do with the parent in the child class.

Timer Version

import random
import sys

import pyqtgraph as pg
from PyQt4 import QtGui, QtCore


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)
        self.button.clicked.connect(self.plotter)

    def plotter(self):
        self.data = [0]
        self.curve = self.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 MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.centralwidget = QtGui.QWidget(self)
        self.setCentralWidget(self.centralwidget)
        self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
        self.login_widget_1 = LoginWidget(self)
        self.horizontalLayout.addWidget(self.login_widget_1)

        self.login_widget_2 = LoginWidget(self)
        self.horizontalLayout.addWidget(self.login_widget_2)

        self.setCentralWidget(self.centralwidget)


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
查看更多
登录 后发表回答