2012-05-13 13 views
5

Seri bağlantı noktasından veri alan bir program yazmaya çalışıyorum ve bu verilere göre Tkinter penceresini gerçek zamanlı olarak otomatik olarak günceller.Seri verilere dayalı olarak Tkinter penceresini dinamik olarak güncelleştirme

Exception in thread Thread-2: Traceback (most recent call last): File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 522, in __bootstrap_inner self.run() File "analysis.py", line 52, in run self.lbl1.pack() File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk/Tkinter.py", line 1764, in pack_configure + self._options(cnf, kw)) RuntimeError: main thread is not in main loop

: bana bu hata veriyor Running

serialdata = [] 
data = True 

class SensorThread(threading.Thread): 
    def run(self): 
     serial = serial.Serial('dev/tty.usbmodem1d11', 9600) 
     try: 
      while True: 
       serialdata.append(serial.readline()) 
     except KeyboardInterrupt: 
      serial.close() 
      exit() 

class GuiThread(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 
     self.root = Tk() 
     self.lbl = Label(self.root, text="") 

    def run(self): 
     self.lbl(pack) 
     self.lbl.after(1000, self.updateGUI) 
     self.root.mainloop() 

    def updateGUI(self): 
     msg = "Data is True" if data else "Data is False" 
     self.lbl["text"] = msg 
     self.root.update() 
     self.lbl.after(1000, self.updateGUI) 

if __name == "__main__": 
    SensorThread().start() 
    GuiThread().start() 

    try: 
     while True: 
      # A bunch of analysis that sets either data = True or data = False based on serialdata 
    except KeyboardInterrupt: 
     exit() 

:

Ben periyodik böyle, pencere ana iş parçacığı güncel verileri alır ve günceller pencere için ayrı bir iş parçacığı oluşturmaya çalıştınız

Bu hatayı google'a gönderdiğimde, çoğunlukla insanların iki farklı ileti dizisinden pencere ile etkileşime geçmeye çalıştığı mesajlar alıyorum, ancak bunu yaptığımı sanmıyorum. Herhangi bir fikir? Çok teşekkürler!

+1

TK parçasını bir iş parçacığında çalıştırmayı denediniz mi? Sadece seri bağlantı noktasını bir iş parçacığında çalıştırın ve TK malzeme ana işlemde kalabilir. Bunun işe yarayabileceğinden şüpheleniyorum ... –

+0

Seri bağlantı noktası verileri ve veri analizi döngüsü için başka bir iş parçacığı almak için bir iş parçacığı gibi mi? Bunu bir atış yapacağım. – user1363445

cevap

6

TK gui'yi bir iş parçacığından çalıştırmayın - ana işlemden çalıştırın. Ben Sen ana iş parçacığı GUI koymak ve seri port yoklamak için ayrı bir iş parçacığı kullanmak gerekir prensibi

from time import sleep 
import threading 
from Tkinter import * 

serialdata = [] 
data = True 

class SensorThread(threading.Thread): 
    def run(self): 
     try: 
      i = 0 
      while True: 
       serialdata.append("Hello %d" % i) 
       i += 1 
       sleep(1) 
     except KeyboardInterrupt: 
      exit() 

class Gui(object): 
    def __init__(self): 
     self.root = Tk() 
     self.lbl = Label(self.root, text="") 
     self.updateGUI() 
     self.readSensor() 

    def run(self): 
     self.lbl.pack() 
     self.lbl.after(1000, self.updateGUI) 
     self.root.mainloop() 

    def updateGUI(self): 
     msg = "Data is True" if data else "Data is False" 
     self.lbl["text"] = msg 
     self.root.update() 
     self.lbl.after(1000, self.updateGUI) 

    def readSensor(self): 
     self.lbl["text"] = serialdata[-1] 
     self.root.update() 
     self.root.after(527, self.readSensor) 

if __name__ == "__main__": 
    SensorThread().start() 
    Gui().run() 
+1

Basit bir liste değişkeni kullanmak yerine iş parçacıkları arasında iletişim kurmak için bir iş parçacığı 'Queue' nesnesini kullanmalısınız. –

+1

Bu daha iyi olurdu, ama benim amacım OP çözümün problemini göstermekti, onlara pythons IPC mekanizmalarını öğretmemek ;-) –

1

gösteriyor içine bir şey örneğini püresi. Seri porttan veri okuduğunuzda, onu bir Queue nesnesine götürebilirsiniz.

Ana GUI iş parçacığında, yoklamayı zamanlamak için after kullanarak sorgulamayı düzenli aralıklarla denetlemek üzere yoklama ayarlayabilirsiniz. Kuyruğu boşaltan bir işlevi çağırın ve ardından sonsuz bir döngü etkin bir şekilde öykünmek için kendisini after ile çağırır.

Sensörden gelen veriler oldukça yavaş bir hızda geliyorsa ve seri bağlantı noktasını engellemeden sorgulayabilirsiniz, bunu ana iş parçacığında yapabilirsiniz - sıradan itme ve çekme yerine Ana iş parçacığı, mevcut veri olup olmadığını görebilir ve varsa okuyabilir. Bunu ancak engelleme olmadan okumak mümkün ise yapabilirsiniz, aksi takdirde GUI verilerinizi beklerken donacaktır.

Örneğin, bu gibi çalışması yapabilir:

def poll_serial_port(self): 
    if serial.has_data(): 
     data = serial.readline() 
     self.lbl.configure(text=data) 
    self.after(100, self.poll_serial_port) 

yukarıda bir anda kapalı bir öğe çekerek, saniyede Seri port 10 kez kontrol edecektir. Elbette gerçek veri koşullarınız için bunu ayarlamanız gerekecek. Bu, has_data gibi bir True yöntemi döndürdüğünüzde ve yalnızca bir okuma engellenmezse, bir yönteminiz olduğunu varsayar.

İlgili konular