2016-11-01 96 views
1

我有一個PyQt程序,承載2個小部件。這個想法是與我的Arduino接口並在程序中顯示Arduinos信息。我無法真正附加我的整個程序,但我會給出亮點。Arduino在PyQt Widget中接口

Arduino的接管串行指令通過ser.write並返回使用ser.read() 所以一個簡單的函數來連續讀取從Arduino的信息後信息將

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

現在我想使用該信息我的PyQt程序中的data但是我不能在我的Qt程序中連續運行一個循環,因爲它永遠不會顯示程序。我已經嘗試使用QThread製作演示程序,但它崩潰,出現錯誤QThread: Destroyed while thread is still running。這是我的演示程序,應該具有與實際程序相似的功能。

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

任何人都可以解釋爲什麼這種情況正在發生或可能在解決如何把簡單的while循環到Qt物件?非常感謝!

回答

1

您需要存儲對QThread的引用,以便它不會被垃圾收集。像這樣:

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

但是需要注意的是,第二次點擊該按鈕會將原始引用替換爲新引用。因此,第一個線程可能會收集垃圾(如果完成,這可能很好)。您可能希望最終考慮一個更復雜的體系結構,在該體系結構中始終有一個線程正在運行,並通過Qt信號/插槽從主線程向Arduino線程發送命令。

另一方面,我認爲在某些時候你會使用arduino的結果來更新一個小部件。請確保你不直接從線程訪問小部件(Qt GUI對象只能從主線程訪問)。相反,您需要從連接到主線程插槽的線程發出一個信號(帶有包含數據的參數)。這個插槽可以安全地訪問GUI對象。

This示出了具有主線程和工作線程之間的雙向通信的更復雜的例子(雖然不與信號發射一起發送的數據,但是這是一個相當微不足道的變化)