【问题标题】:draw matplotlib graph with QThread issue使用 QThread 问题绘制 matplotlib 图
【发布时间】:2017-06-07 06:30:46
【问题描述】:

在主类 Window 之外,我定义了新类 (test_graph_Data),它将使用 matplotlib 绘制图形。为了避免警报“QPixmap:在 GUI 线程之外使用像素图不安全”的问题,我定义了新类 test_graph_Data,它将向主类发出信号以绘制图形,但是发出一些问题信号...看下面的代码:

当我运行代码时,我收到警告: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()

【问题讨论】:

  • @eyllanesc 这就是重点。在 test_graph_Data 类中初始化图形后,我想向主线程发送信号以显示图形...例如数组 b = [1,0,1,0,1,0,1,1,1,1,0 ,1,0,1] 就像代码中所述。最主要的是该图应该在其他线程中初始化,而不是在主线程中。

标签: python matplotlib pyqt pyqt4 qthread


【解决方案1】:

您必须使用线程来操作数据,而不是绘制图表。在这个例子中,我让你的列表轮换了。您必须创建一个与主线程通信的信号,表明数据已准备好更新。在 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()

【讨论】:

  • 就是这样!非常感谢!有一些改进代码的技巧,比如删除“import matplotlib as mpl mpl.use("QT4Agg")”行,但你明白了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-21
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多