2013-06-05 60 views
3

我對python和pyserial很新。我的電腦安裝了Python 2.7.4與pyserial,我想打印串行接收的數據在我的電腦上的一個單獨的窗口。首先必須打開窗口,然後在該窗口上打印串行數據。在這裏窗口必須打開一次,串行數據必須連續打印在窗口上,直到設備停止發送數據。 我嘗試過使用這段代碼,但它毫無價值。 請有人幫我的代碼。用於在窗口上打印串行數據的python代碼。

import serial 
import Tkinter 
from Tkinter import * 
s = serial.Serial('COM10',9600) # open serial port 
master = Tk() 
master.geometry("1360x750")  # a window pop up with width (1360) and height(750)  which exatly fits my monitor screen.. 

while 1: 
if s.inWaiting(): 
text = s.readline(s.inWaiting()) 
frameLabel = Frame(master, padx=40, pady =40) 
frameLabel.pack() 
w = Text(frameLabel, wrap='word', font="TimesNewRoman 37") 
w.insert(12.0,text) 
w.pack() 
w.configure(bg=master.cget('bg'), relief='flat', state='Normal') 

mainloop() 
+0

你可能會看看這個答案的第一部分http://stackoverflow.com/a/14040516。它顯示瞭如何在tkinter循環中重複調用一個函數。這基本上是你想要做的,而不是'while True'循環。 – FabienAndre

+0

非常感謝您的快速回復。我將嘗試在tkinter循環中使用函數。 – Steve

回答

4

這裏的問題是,你有兩個循環,應該是持續運行:爲GUI主循環和用於傳輸串行數據的循環。你能做些什麼來解決這個是開始一個新的線程接收串口的內容,把它放在一個Queue,並在GUI中定期檢查線程隊列的內容:

import serial 
import threading 
import Queue 
import Tkinter as tk 


class SerialThread(threading.Thread): 
    def __init__(self, queue): 
     threading.Thread.__init__(self) 
     self.queue = queue 
    def run(self): 
     s = serial.Serial('COM10',9600) 
     while True: 
      if s.inWaiting(): 
       text = s.readline(s.inWaiting()) 
       self.queue.put(text) 

class App(tk.Tk): 
    def __init__(self): 
     tk.Tk.__init__(self) 
     self.geometry("1360x750") 
     frameLabel = tk.Frame(self, padx=40, pady =40) 
     self.text = tk.Text(frameLabel, wrap='word', font='TimesNewRoman 37', 
          bg=self.cget('bg'), relief='flat') 
     frameLabel.pack() 
     self.text.pack() 
     self.queue = Queue.Queue() 
     thread = SerialThread(self.queue) 
     thread.start() 
     self.process_serial() 

    def process_serial(self): 
     while self.queue.qsize(): 
      try: 
       self.text.delete(1.0, 'end') 
       self.text.insert('end', self.queue.get()) 
      except Queue.Empty: 
       pass 
     self.after(100, self.process_serial) 

app = App() 
app.mainloop() 

我的天堂沒有嘗試過這個程序,但我認爲你可以獲得關於如何使用它的全局想法。

+0

串行對象是不是提供了一個類似隊列的api,因此足以用作隊列?換句話說,檢查'inWaiting()'並直接從'process_serial'循環讀取就足夠了嗎? – FabienAndre

+0

@FabienAndre問題不是從串口讀取,而是你同時運行兩個循環的事實。隊列(結合'after'方法)是在不凍結GUI的情況下傳遞兩個線程的安全方式。 –

+0

我完全同意隊列是處理兩個線程的正確方法。我的問題是,如果在這種情況下,是否需要(以及爲什麼)使用第二個線程而不是從Tkinter'after loop'讀取序列。爲了更清楚一點,爲什麼不用'serial.read'替換'serial.inWaiting'和'queue.get'的'queue.qsize'檢查? – FabienAndre