Python:尽管有线程,代码完成后GUI才会更新

时间:2014-01-24 08:39:45

标签: python multithreading tkinter queue

我有一个python模块“命令行阅读器”,通过RFID与一个小型电子单元进行通信。我想创建一个使用该程序的GUI,并进一步处理数据。

我的问题是GUI标签没有更新。我尝试使用论坛中提出的线程和队列,但标签在代码完成之前仍然没有。 以下是我从此示例改编的简化代码:http://code.activestate.com/recipes/82965-threads-tkinter-and-asynchronous-io/

谁能告诉我我做错了什么?

from GUI_reader import Commandline_Reader
from Tkinter import *
import Tkinter as ttk
import ttk
import time
import threading
import Queue

class GuiPart:
    def __init__(self, master, queue, out_queue, check_queue):
        self.queue = queue
        self.out_queue = out_queue
        self.check_queue = check_queue
        self.master = master     
        self.master.title("AO Fracture Monitor")

        self.patid = StringVar()
        self.text = StringVar()
        self.startvar = BooleanVar()

        # Patient ID
        idf = ttk.Labelframe(master, text='Patient ID')
        idf.grid(column=0, row=0, sticky=(N,E,W,S))

        self.idl = ttk.Label(idf, text='none')
        self.idl.grid(padx=5, pady=(5,10))

        # Info text
        self.infotext = Label(master, height=6, text='first', justify='left', anchor=N)
        self.infotext.grid(row=1, column=0, padx=5, pady=5, sticky=(N,E,S,W))

        #Start button
        button = ttk.Checkbutton(master, text='Start', variable=self.startvar, style='TButton', command=self.go)
        button.grid(column=0, row=2, sticky=(E,S,W))

    def go(self):
        ThreadedClient(root).go()

    def processIncoming(self):
        while self.check_queue.qsize():
            try:
                text = self.check_queue.get(0)
                # text = ['text', 'searching for logger'],['ID', '266525']
                if text[0] == 'ID':
                    print text
                    self.idl.configure(text=text[1])
                    self.infotext.configure(text='Process executed')
                elif text[0] == 'text':
                    print text
                    self.infotext.configure(text=text[1])
            except self.check_queue.empty():
                pass

class ThreadedClient:
    def __init__(self, master):
        self.master = master
        self.queue = Queue.Queue()
        self.out_queue = Queue.Queue()
        self.check_queue = Queue.Queue()
        self.gui = GuiPart(master, self.queue, self.out_queue, self.check_queue)
        self.running = True

    def go(self):    
        self.queue.put('-s --get_serial_number')
        self.thread = threading.Thread(target = self.workerThread1)
        self.thread.start()
        self.periodicCall()
        self.check_queue.put(['text','searching for logger'])

        while self.out_queue.empty():
            time.sleep(1)
            print 'wait...'
        output = self.out_queue.get()
        # output = ['COM3' , ... , 'done']
        while output[-1] != 'done':
            time.sleep(2)
            print 'wait...'
        for i, s in enumerate(output):
            if 'serial_number' in s:
                ID = output[i]
                # ID = 'serial_number=266525'
        self.check_queue.put(['ID',ID[14:]])

    def periodicCall(self):
        self.gui.processIncoming()
        if not self.running:
            return
        self.master.after(100, self.periodicCall)

    def workerThread1(self):
        self.argString = self.queue.get()
        reader = Commandline_Reader(self.argString)
        if reader.connect():
            self.out_queue.put(reader.run())
            if reader.output[-1] == 'done':
                self.queue.task_done()

        self.running = False


if __name__ == "__main__":
    root = Tk()
    client = ThreadedClient(root)
    root.mainloop() 

1 个答案:

答案 0 :(得分:0)

您的问题可能是这两个循环,但可能还有其他问题:

while self.out_queue.empty():
    time.sleep(1)
    print 'wait...'
...
while output[-1] != 'done':
    time.sleep(2)
    print 'wait...'

你永远不应该在GUI线程中调用sleep,因为它会阻止GUI响应事件。