2016-11-01 6 views
1

Ich habe ein PyQt-Programm, das 2 Widgets hostet. Die Idee ist, mit meinem Arduino zu interagieren und die Arduinos-Informationen im Programm anzuzeigen. Ich kann nicht wirklich mein ganzes Programm anhängen, aber ich werde die Highlights geben.Arduino Interfacing innerhalb PyQt Widget

Der Arduino einen Befehl über serielle über ser.write nimmt und die nachfolgenden Informationen ser.read() So eine einfache Funktion wäre, die Informationen aus dem Arduino kontinuierlich lesen mit

while True: 
    ser.write(command.encode() 
    time.sleep(.1) 
    resp=ser.read() 
    data=struct.unpack('<b',resp) 

Jetzt mag ich die Informationen verwenden, in data in meinem PyQt-Programm, aber ich kann nicht kontinuierlich eine Schleife in meinem Qt-Programm ausführen, weil es das Programm nie anzeigen wird. Ich habe versucht, QThread zu verwenden, indem ich ein Demo-Programm mache, aber es stürzt mit Fehler QThread: Destroyed while thread is still running ab. Dies ist mein Demo-Programm, das ähnliche Funktionen wie das eigentliche Programm haben sollte.

import sys 
import urllib 
import urllib.request 
import serial 
import time 
from PyQt4 import QtCore, QtGui 


class CmdThread(QtCore.QThread): 
    def __init__(self): 
     QtCore.QThread.__init__(self) 
     BASIC="\x24\x4d\x3c\x00" 

     self.ser=serial.Serial() 
     #ser.port="COM12" 
     self.ser.port='COM12' 
     self.ser.baudrate=115200 
     self.ser.bytesize = serial.EIGHTBITS 
     self.ser.parity = serial.PARITY_NONE 
     self.ser.stopbits = serial.STOPBITS_ONE 
     self.ser.timeout = 0 
     self.ser.xonxoff = False 
     self.ser.rtscts = False 
     self.ser.dsrdtr = False 
     self.ser.writeTimeout = 2 
     self.ser.open() 
     print('Initializing in 10 seconds...') 
     time.sleep(10) 

    def run(self): 
     self.ser.write(self.BASIC.encode()) 
     time.sleep(0.1) 
     resp=self.ser.read() 
     datalength=struct.unpack('<b',resp)[0] 
     data=self.ser.read(datalength+1) 
     data=data[4:-1] 
     temp=struct.unpack('<'+'h'*(int(len(data)/2)),data) 
     self.ser.flushInput() 
     self.ser.flushOutput() 
     print((temp[0]/10,temp[1]/10,temp[2])) 


class MainWindow(QtGui.QWidget): 
    def __init__(self): 
     super(MainWindow, self).__init__() 
     self.list_widget = QtGui.QListWidget() 
     self.button = QtGui.QPushButton("Start") 
     self.button.clicked.connect(self.start_cmd) 
     layout = QtGui.QVBoxLayout() 
     layout.addWidget(self.button) 
     layout.addWidget(self.list_widget) 
     self.setLayout(layout) 

    def start_cmd(self): 
     downloader = CmdThread() 
     downloader.start() 

if __name__ == "__main__": 
    app = QtGui.QApplication(sys.argv) 
    window = MainWindow() 
    window.resize(640, 480) 
    window.show() 
    sys.exit(app.exec_()) 

Kann mir jemand erklären, warum dies geschieht oder vielleicht eine Lösung, wie die einfachere while Schleife in eine Qt-Widget zu integrieren? Vielen Dank!

Antwort

1

Sie müssen einen Verweis auf die QThread speichern, so dass es nicht Müll gesammelt wird. So ist das:

Aber seien Sie gewarnt, dass das Klicken der Taste ein zweites Mal die ursprüngliche Referenz durch eine neue ersetzen wird. Und so kann der erste Thread Müll sammeln (was wahrscheinlich in Ordnung ist, wenn er fertig ist). Vielleicht möchten Sie eine komplexere Architektur in Erwägung ziehen, in der Sie immer einen Thread ausführen und Befehle vom Hauptthread über Qt-Signale/Slots an den Arduino-Thread senden.

Bei einer anderen Notiz, ich nehme an, irgendwann werden Sie die Ergebnisse aus dem Arduino verwenden, um ein Widget zu aktualisieren. Bitte stellen Sie sicher, dass Sie nicht direkt vom Thread auf das Widget zugreifen (auf Qt-GUI-Objekte sollte immer nur vom Haupt-Thread zugegriffen werden). Stattdessen müssen Sie ein Signal (mit einem Parameter, der Ihre Daten enthält) aus dem Thread ausgeben, der mit einem Slot im Haupt-Thread verbunden ist. Dieser Slot ist dann in der Lage, sicher auf die GUI-Objekte zuzugreifen.

This zeigt ein komplexeres Beispiel mit zwei-Wege-Kommunikation zwischen dem Haupt-Thread und ein Arbeiter-Thread (wenn auch ohne die Daten zusammen mit der Signalabgabe zu senden, aber das ist ein ziemlich trivial ändern)

Verwandte Themen