2017-01-23 1 views
1

Als eine Fortsetzung der Frage ich habe here vor einigen Tagen gelöst, habe ich eine PyQt4 GUI, die zwei PyQtGraphPlotWidgets bettet, die jeweils Daten von einem Thread zufällig angehängt Array durch ausgelöst ein Knopf. Es funktioniert wunderbar und die Benutzeroberfläche reagiert. Aber es kommt ein Punkt, wo die Graphen aufhören, die Aktualisierungen in ihren jeweiligen PlotWidgets anzuzeigen, und ich muss minimieren/maximieren, um die in den PlotWidgets gezeichneten Aktualisierungen zu sehen. Der Code sieht so aus:QThreading PyQtGraph PlotWidgets in PyQt4

import random 
import sys 

import pyqtgraph as pg 
import time 
from PyQt4 import QtGui, QtCore 


class MyThread(QtCore.QThread): 
    def __init__(self, curve, parent=None): 
     super(MyThread, self).__init__(parent=parent) 
     self.curve = curve 
     self.data = [0] 
     app.processEvents()#increases the time the drawings are shown 

    def run(self): 
     app.processEvents() #increases the time the drawings are shown 
     while True: 
      self.data.append(self.data[-1] + 0.2 * (0.5 - random.random())) 
      self.curve.setData(self.data, downsample=10) #crashes without 
      time.sleep(0.1) 


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) 
     app.processEvents() 

    def plotter(self): 
     self.curve = self.plot.getPlotItem().plot() 
     myThread = MyThread(self.curve, self) 
     myThread.start() 


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__': 
    global app 
    app = QtGui.QApplication(sys.argv) 
    w = MainWindow() 
    w.show()  
    sys.exit(app.exec_()) 

Jeder Hinweis oder Abhilfe für das, was ich tun kann, für nicht mit, um das Updates in der GUI zu bekommen macht mich unglaublich froh zu maximieren/zu minimieren.

Im Anschluss an die Beratung von @ImportanceOfBeingErnest in der Antwort unten, habe ich versucht, die Python Wiki im Anschluss an die GUI und den Faden mit Signalen und Slots zu verbinden:

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


class MyThread(QtCore.QThread): 
    def __init__(self, parent=None): 
     super(MyThread, self).__init__(parent=parent) 
     self.data = [0] 

    def run(self): 
     while True: 
      self.data.append(self.data[-1] + 0.2 * (0.5 - random.random())) 
      self.emit(SIGNAL("output(data)"), self.data) 
      time.sleep(0.1) 


class LoginWidget(QtGui.QWidget): 
    def __init__(self, parent=None): 
     super(LoginWidget, self).__init__(parent) 
     self.myThread = MyThread() 
     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) 
     self.connect(self.myThread, SIGNAL("output(data)"), self.plotter) 

    def plotter(self, data): 
     self.curve = self.plot.getPlotItem().plot() 
     self.curve.setData(data, downsample=10) 


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

Aber das gibt mir den Fehler:

"in self.connect(self.myThread, SIGNAL("output(data)"), self.plotter) 
NameError: name 'SIGNAL' is not defined" 

durch ein question from 4 years ago lesen, ich SIGNAL durch QtCore.SIGNAL ersetzen die folgenden Fehler zu erhalten:

"in self.connect(self.myThread, QtCore.SIGNAL("output(data)"), self.plotter) 
TypeError: C++ type 'data' is not supported as a slot argument type" 

dann durch die Typeerror ingnoring wie:

try: 
    self.connect(self.myThread, QtCore.SIGNAL("output(data)"), self.plotter) 
except TypeError: 
    pass 

Die GUI startet, aber wenn ich auf schließlich die Taste und eine Verbindung zum self.plotter Funktion ich die folgende Fehlermeldung erhalten:

"in plotter 
self.curve.setData(data, downsample=10) 
File "C:\Users\iyv\AppData\Local\Programs\Python\Python34_64\lib\site- 
packages\pyqtgraph\graphicsItems\PlotDataItem.py", line 381, in setData 
raise Exception('Invalid data type %s' % type(data)) 
Exception: Invalid data type <class 'bool'>" 

Ich bin ziemlich verwirrt. Soll ich PyQtGraph kontaktieren? Jede Hilfe wurde dankbar angenommen.

+0

Ich habe meine Antwort unten bearbeitet, um ein funktionierendes Beispiel zu zeigen. – ImportanceOfBeingErnest

Antwort

2

Sie müssen die GUI und den Thread getrennt halten. Sie dürfen in diesem Fall kein GUI-Objekt wie das Diagramm-Widget verwenden!

Ich bin nicht sicher, ob Sie Threading benötigen, da Ihre Daten nicht sehr groß sind und nur 10 Mal pro Sekunde aktualisiert werden. Aber wenn Sie sich entscheiden, es zu verwenden, verwenden Sie nur signals and slots, um zwischen Thread und GUI zu kommunizieren.


Unten ist eine modifizierte Version Ihres Programms, die Threading verwendet und funktioniert gut. Es verwendet den neuen Stil signals and slots. Dies ist hoffentlich einfacher zu verstehen, da Sie einfach object als Datentyp verwenden können.

Zwei Dinge hat keinen Sinn in Ihrem Programm machen, sind:

  • Sie self.curve im Plotten Slot neu definieren.
  • rufen Sie den Plot-Slot beim Drücken der Taste. Stattdessen sollte ein Knopfdruck den Thread starten.

Ich habe sie korrigiert.

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


class MyThread(QtCore.QThread): 
    signal = QtCore.pyqtSignal(object) 
    def __init__(self, parent=None): 
     super(MyThread, self).__init__(parent=parent) 
     self.data = [0] 

    def __del__(self): 
     self.exiting = True 
     self.wait() 

    def run(self): 
     while True: 
      self.data.append(random.random()) 
      self.signal.emit(self.data) 
      time.sleep(0.1) 


class LoginWidget(QtGui.QWidget): 
    def __init__(self, parent=None): 
     super(LoginWidget, self).__init__(parent) 
     self.myThread = MyThread() 
     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.curve = self.plot.getPlotItem().plot() 
     self.button.clicked.connect(self.start) 


    def plotter(self, data): 
     self.curve.setData(data) 

    def start(self): 
     self.myThread.start() 
     self.myThread.signal.connect(self.plotter) 


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