简体   繁体   中英

Python: GUI does not update until code is finished despite threading

I have a python module "commandline reader" that communicates via RFID with a small electronic unit. I want to create a GUI that uses this program and further processes the data.

My problem was that the GUI labels didn't update. I tried to use threading and queues as proposed in the forum, but the labels still don't before the code is finished. Here's my simplified code adapted from this example: http://code.activestate.com/recipes/82965-threads-tkinter-and-asynchronous-io/

Can anyone tell me what I'm doing wrong?

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

Your problem is likely these two loops, though there may be other problems:

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

'

You should never, ever call sleep in the GUI thread, because it prevents the GUI from responding to events.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM