2017-08-08 150 views
1

我想创建一个不确定的进度条在python 3在新的顶级窗口的某些过程,然后启动该进程的线程。我想要的是进度条启动并且线程也在后台启动,一旦线程完成执行,一些消息显示任务已完成。如何创建一个不确定的进度,并在后台启动一个线程,并在Python中完成线程后再次执行一些操作

代码:

class myThread(threading.Thread): 
    def __init__(self, threadID): 
     threading.Thread.__init__(self) 
     self.threadID = threadID 


    def run(self): 
     print("Starting the thread") 
     func() 
     print("Ending the thread") 

def func(): 
    some task 

... 
new_top = Toplevel() 
new_top.title("New Top Level") 
new_top.geometry("400x170") 

label = Label(new_top, text='Doing some work', justify=CENTER, bg="#CBFDCB").place(x=43,y=30) 

progress_bar = ttk.Progressbar(new_top, orient="horizontal", mode="indeterminate", takefocus=True, length=320) 
progress_bar.place(x=40, y=80) 
progress_bar.start() 

thread1 = myThread(1) 
thread1.start() 
thread1.join() 

... 

执行后的线程操作

我的问题是什么,带标签和进度条的顶层窗口,如果thread1.join()被调用永远不会出现,如果我跳过此部分,那么操作后线程执行不会运行

回答

0

用Tkinter对线程进行线程化可能有点棘手。这里有一些代码可以实现你想要的功能。我的第一个版本无法正常工作,因为我试图从线程的.run方法中销毁Tkinter窗口。这不起作用:窗口关闭,但root.destroy调用后.run方法没有进展。所以现在我们有一个函数每隔100毫秒检查一次线程是否仍然活着,如果它没有活动,我们关闭Tkinter窗口。

import threading 
import tkinter as tk 
from tkinter import ttk 
from time import sleep 

class myThread(threading.Thread): 
    def __init__(self, threadID): 
     threading.Thread.__init__(self) 
     self.threadID = threadID 

    def run(self): 
     print("Starting the thread") 
     func() 
     print("Ending the thread") 

def func(): 
    for i in range(10): 
     print(i) 
     sleep(1) 

def check_thread(th): 
    if not th.isAlive(): 
     root.destroy() 
    root.after(100, check_thread, th) 

root = tk.Tk() 
root.title("New Top Level") 
root.geometry("400x170") 

tk.Label(root, text='Doing some work', justify=tk.CENTER, bg="#CBFDCB").place(x=43, y=30) 
progress_bar = ttk.Progressbar(root, orient="horizontal", 
    mode="indeterminate", takefocus=True, length=320) 
progress_bar.place(x=40, y=80) 
progress_bar.start() 

thread1 = myThread(1) 
thread1.start() 
root.after(100, check_thread, thread1) 
root.mainloop() 

print("Doing post-thread stuff") 
0

TKinter通过使用无限主循环来等待和处理事件 - 截取按下按钮,重绘元素等(看看here了解更多信息)。

当你调用join()时,你强制你的主线程(在其中运行tkinter)等待,直到你刚刚开始的线程完成执行,然后再继续,因此它无法绘制带有进度条的顶级窗口。因此,这不是一个真正的选择。

另一方面,您需要知道您的子线程何时完成执行。您可以使用mythread.isAlive()来检查线程是否仍然存在,但是不能在循环中执行它,因为它会再次停止执行tkinter的主循环,从而绘制界面。我建议寻找at the answer here来处理这个问题。

相关问题