2017-01-22 88 views
1

在主类窗口旁边,我定义了新类(test_graph_Data),它将使用matplotlib绘制图形。为了避免报警问题“QPixmap:在GUI线程之外使用pixmaps是不安全的”,我已经定义了新的类test_graph_Data,它会向主类发出信号以绘制图形,但是有一些问题需要发出信号...看看下面的代码:PyQt,QThread,绘制带有QThread问题的matplotlib图形

当我运行代码,我得到了警告:AttributeError:“PyQt4.QtCore.pyqtSignal”对象没有属性'连接'!

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() 
+0

您不能在主线程(GUI线程)以外的其他线程中显示任何图形。 你想图什么? – eyllanesc

+0

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

回答

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() 
+0

就是这样!非常感谢!有一些改进代码的提示,比如删除“import matplotlib as mpl mpl.use(”QT4Agg“)”,但你明白了! –

+0

问题是我已经安装了pyqt4和pyqt5,但是我把那条线与pyqt的版本有问题。 – eyllanesc