在主任务中显示来自后台任务的计数变量(Tkinter GUI)

时间:2016-08-11 11:49:16

标签: python multithreading python-2.7 user-interface tkinter

我正在尝试在主要任务中显示来自后台任务的计数变量,这是我的tkinter GUI。为什么?我想显示长时间执行后台任务正在执行,然后使用此计数变量使用进度条可视化它。

我的问题是,即使使用Queue,我也无法显示计数变量。也许我在理解python及其对象和/或线程的行为方面遇到了问题。

import threading
import time
import Queue
import Tkinter as Tk
import Tkconstants as TkConst
from ScrolledText import ScrolledText
from tkFont import Font
import loop_simulation as loop

def on_after_elapsed():
    while True:
        try:
            v = dataQ.get(timeout=0.1)
        except:
            break
        scrText.insert(TkConst.END, str(v))     # "value=%d\n" % v
        scrText.see(TkConst.END)
        scrText.update()
    top.after(100, on_after_elapsed)

def thread_proc1():
    x = -1
    dataQ.put(x)
    x = loop.loop_simulation().start_counting()
    # th_proc = threading.Thread(target=x.start_counting())
    # th_proc.start()

    for i in range(5):
        for j in range(20):
            dataQ.put(x.get_i())
            time.sleep(0.1)
            # x += 1
        time.sleep(0.5)
    dataQ.put(x.get_i())

top = Tk.Tk()
dataQ = Queue.Queue(maxsize=0)
f = Font(family='Courier New', size=12)
scrText = ScrolledText(master=top, height=20, width=120, font=f)
scrText.pack(fill=TkConst.BOTH, side=TkConst.LEFT, padx=15, pady=15, expand=True)

th = threading.Thread(target=thread_proc1)
th.start()
top.after(100, on_after_elapsed)
top.mainloop()
th.join()

thread_proc1()中我想得到后台任务计数器的值。这是后台任务:

import time

class loop_simulation:

    def __init__(self):
        self.j = 0
        # self.start_counting()

    def start_counting(self):
        for i in range(0, 1000000):
            self.j = i
            time.sleep(0.5)

    def get_i(self):
        return str(self.j)

1 个答案:

答案 0 :(得分:0)

计数变量未显示的原因是

    x = loop.loop_simulation().start_counting()
thread_proc1()中的

声明。这会创建一个loop_simulation实例并调用其start_counting()方法。但是,除了已经在-1中插入dataQ之外,thread_proc1()start_counting()返回之前不做任何其他事情,而这不会是很长时间(500K秒)。

与此同时,您的脚本的其余部分正在运行,并且只显示放入的初始-1

另请注意,如果start_counting()确实返回,则其None的值将分配给x,以后的代码会尝试将其用于:x.get_i()。< / p>

下面是修复这些问题的代码的重新编写,并且更紧密地遵循PEP 8 - Style Guide for Python Code。为了避免调用start_counting()的主要问题,我将loop_simulation类更改为threading.Thread的子类并将其重命名为LoopSimulation,并在{{1}中创建它的实例因此,除了处理基于tkinter的GUI的主要线程之外,现在有两个后台线程。

thread_proc1

import loop_simulation as loop from ScrolledText import ScrolledText import threading import Tkinter as Tk import Tkconstants as TkConst from tkFont import Font import time import Queue def on_after_elapsed(): # removes all data currently in the queue and displays it in the text box while True: try: v = dataQ.get_nowait() scrText.insert(TkConst.END, str(v)+'\n') scrText.see(TkConst.END) except Queue.Empty: top.after(100, on_after_elapsed) break def thread_proc1(): dataQ.put(-1) ls = loop.LoopSimulation() # slow background task Thread ls.start_counting() while ls.is_alive(): # background task still running? for i in range(5): for j in range(20): dataQ.put(ls.get_i()) time.sleep(0.1) time.sleep(0.5) dataQ.put('background task finished') top = Tk.Tk() dataQ = Queue.Queue(maxsize=0) font = Font(family='Courier New', size=12) scrText = ScrolledText(top, height=20, width=120, font=font) scrText.pack(fill=TkConst.BOTH, side=TkConst.LEFT, padx=15, pady=15, expand=TkConst.YES) th = threading.Thread(target=thread_proc1) th.daemon = True # OK for main to exit even if thread is still running th.start() top.after(100, on_after_elapsed) top.mainloop() 模块:

loop_simulation.py