在 PyQt4 #2 中使用 PyQtGraph 进行实时绘图

Posted

技术标签:

【中文标题】在 PyQt4 #2 中使用 PyQtGraph 进行实时绘图【英文标题】:Live Plotting with PyQtGraph in PyQt4 #2 【发布时间】:2017-06-02 18:57:55 【问题描述】:

首先对篇幅表示抱歉。我想尽可能地解释我的问题。我对 Python 很陌生,并试图使用嵌入在 PyQt4 中的 PyQtGraph 制作一个绘图应用程序。几天前,我的plotting problem 得到了一个非常好的答案,我的下一步是让两个 PyQtGraphs 绘图小部件同时在同一个 PyQt4 的 CentralWidget 中绘图。通过与描述的链接相同的方法,两个图都可以正常工作,但是 GUI 没有响应。为了克服这个问题,我的目标是使用QThread,为此,我需要在不同的类中使用我的绘图功能。但是我弄乱了我的变量,看不到如何:

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

这给了我一个 Plots.plotter 错误:

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

如果在 MainWindow 类中我将“button.connect”参数替换为 Plots.print,它可以正常工作。所以我可以看到我在 MainWindow 中创建了一个 LoginWidget 对象,然后 Plots 从 MainWindow 继承,再次调用相同的 LoginWidget 对象这一事实有问题。

我尝试了一个建议的解决方案,其中父亲(MainWindow)不访问孩子(Plots)的方法。但是,如果从 Plots 中,我想调用我打算放置线程的类,我会再次遇到同样的错误....

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

【问题讨论】:

您的代码给了我一个不同的错误。 self.login_widget.button.clicked.connect(Plots.plotter) AttributeError: 'function' 对象没有属性 'pyqtSignature' 当您在 self.login_widget.button.clicked.connect(Plots.plotter) 中将 Plots.plotter 替换为 Plots.print 时是否会出现相同的错误? 【参考方案1】:

在继承中,父类不应该访问子类的方法,最好在子类中继承和实现与父类无关的新方法。

定时器版本

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

【讨论】:

谢谢,但这并不能解决我的问题。 “我需要在不同的类中拥有我的绘图功能”,才能使用 QThread。所以,如果我只是创建一个同样从 MainWindow 继承的新类并调用它,我会得到同样的错误。在这种情况下,我不会将我的插槽调用位置放在我继承的类(MainWindow)中,而是在 Plots 中,正如你所建议的那样。 @Ivy 你能放一张你想要的照片吗? 我希望在同一个小部件中包含两个按钮和两个图表。每个按钮都会触发一个图表,就像上面的单个图表示例一样,并且应用程序仍然是响应式的,就像上面的单个图表示例一样。 @Ivy 要使用线程,不必有不同的类。 谢谢@eyllanesc,我很感激。线程看起来很有趣:GUI 是响应式的! :-) 但它会以不同的延迟更新,并且其中一个线程在短时间内被销毁。我将在 QThread 上工作以使其正常工作。

以上是关于在 PyQt4 #2 中使用 PyQtGraph 进行实时绘图的主要内容,如果未能解决你的问题,请参考以下文章

pyqtgraph删除pyqt4 gui中的持久图例

PyQt4 中的 QThreading PyQtGraph PlotWidgets

Pyqt4-pyqtgraph 应用程序递归打开自身的新实例

在 PyQtGraph 中反转 Y 轴

PyQtGraph 图在 Qt MainWindow 上显示不正确

pyqtgraph 轴未正确显示