2016-11-01 100 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示出了具有主线程和工作线程之间的双向通信的更复杂的例子(虽然不与信号发射一起发送的数据,但是这是一个相当微不足道的变化)