使用 QThread 问题绘制 matplotlib 图

draw matplotlib graph with QThread issue

除了主要的 class Window,我还定义了新的 class (test_graph_Data),它将使用 matplotlib 绘制图形。为了避免alarm "QPixmap: It is not safe to use pixmaps outside the GUI thread"的问题,我定义了new class test_graph_Data,它会向main class发出信号来绘制图形,但是有一些问题发出信号...看下面的代码:

当我 运行 代码时,我收到警告:AttributeError: "PyQt4.QtCore.pyqtSignal" object has no attribute 'connect'!

import sys, time
from PyQt4 import QtGui, QtCore
import matplotlib.pyplot as plt

class Window(QtGui.QMainWindow):

     def __init__(self):
        super(Window, self).__init__()
        self.setGeometry(50, 50, 120, 90)
        self.home()

    def home(self):
        self.test = QtGui.QPushButton("Test", self)
        self.test.clicked.connect(self.test1_function)
        self.test.move(10,20)
        self.show()

    def test1_function(self):
        self.get_thread = test_graph_Data()
        self.connect(self.get_thread, QtCore.SIGNAL("finished()"),self.done_test1_function)
        self.get_thread.start()

    def done_test1_function(self):
        print 'Graph is displayed!'

class test_graph_Data(QtCore.QThread) :
    def __init__(self):
        QtCore.QThread.__init__(self)

    def __del__(self):
        self.wait()

    def graph_data(self):
        start = time.time()
        b = [1,0,1,0,1,0,1,1,1,1,0,1,0,1]
        plt.ion()
        fig1 = plt.figure()
        ax1 = fig1.add_subplot(111)
        ax1.plot(b, 'b')
        end = time.time()
        print end - start

    def run(self):
        top_post = self.graph_data()

def main():
    app = QtGui.QApplication(sys.argv)
    GUI = Window()
    GUI.show()
    sys.exit(app.exec_())


if __name__ == '__main__' :
    main()

您必须使用线程来操作数据,而不是绘图。在这个例子中,我让你的列表旋转。您必须创建一个信号来通知主线程数据已准备好更新。在 GUI 中,您必须将该信号与更新图形的函数连接起来。

import sys
import time
import matplotlib as mpl
mpl.use("QT4Agg")
import matplotlib.pyplot as plt
from PyQt4 import QtGui, QtCore


class test_graph_Data(QtCore.QThread):
    updated = QtCore.pyqtSignal(list)
    running = True

    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.b = [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1]

    def run(self):
        while self.running:
            # rotate list
            self.b = self.b[1:] + [self.b[0]]
            self.updated.emit(self.b)
            time.sleep(0.1)


class Window(QtGui.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.setGeometry(50, 50, 120, 90)
        self.home()

    def home(self):
        self.test = QtGui.QPushButton("Test", self)
        self.test.clicked.connect(self.test1_function)
        self.test.move(10, 20)
        self.show()

    def test1_function(self):
        self.get_thread = test_graph_Data(self)
        self.get_thread.finished.connect(self.done_test1_function)
        self.get_thread.updated.connect(self.graph_data)
        plt.ion()
        fig1 = plt.figure()
        self.ax1 = fig1.add_subplot(111)
        self.get_thread.start()

    def done_test1_function(self):
        print('Graph is displayed!')

    def graph_data(self, data):
        self.ax1.clear()
        self.ax1.plot(data, 'b')

    def closeEvent(self, event):
        self.get_thread.running = False
        self.get_thread.wait()


def main():
    app = QtGui.QApplication(sys.argv)
    GUI = Window()
    GUI.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()