嗨Python和Tkinter Gurus, 我正在尝试构建一个具有两个按钮的简单GUI。单击Button时,会启动一个线程来完成一些工作。这项工作通常需要10秒/ 15秒。 GUI也可以正常工作。
但是我想实现一个弹出窗口来通知哪个线程已经完成。我检查了t.isAlive()
函数并且无法实现它,因为我不知道如何在主循环中基于isAlive触发事件。
这是我的示例代码
from threading import Thread
from time import sleep
import Tkinter
import ttk
class SmallGui:
def __init__(self, master):
self.master = master
self.master.title('test gui')
self.button_1 = ttk.Button(self.master,
text='Start 1',
command=lambda: self.init_thread(1))
self.button_2 = ttk.Button(self.master,
text='Start 2',
command=lambda: self.init_thread(2))
self.button_1.pack()
self.button_2.pack()
def init_thread(self, work):
if work == 1:
t = Thread(target=self.work_1)
t.start()
else:
t = Thread(target=self.work_2)
t.start()
@staticmethod
def work_1():
print 'Work 1 started'
# Do some Task and return a list
sleep(10)
@staticmethod
def work_2():
print 'Work 2 Started'
# Do some Task and return a list
sleep(15)
if __name__ == '__main__':
root = Tkinter.Tk()
run_gui = SmallGui(root)
root.mainloop()
答案 0 :(得分:1)
您可以使用tkinter的消息框。 Tkinter有一个内置方法,可用于各种弹出消息或问题。在这里,我们将使用messagebox.showinfo
。
我正在使用Python 3.X,所以我添加了一个适用于3.X和2.X版python的导入方法。
from threading import Thread
from time import sleep
try:
import Tkinter as tk
import tkMessageBox as mb
import ttk
except ImportError:
import tkinter as tk
from tkinter import messagebox as mb
import tkinter.ttk as ttk
class SmallGui:
def __init__(self, master):
self.master = master
self.master.title('test gui')
self.button_1 = ttk.Button(self.master,
text='Start 1',
command=lambda: self.init_thread(1))
self.button_2 = ttk.Button(self.master,
text='Start 2',
command=lambda: self.init_thread(2))
self.button_1.pack()
self.button_2.pack()
def init_thread(self, work):
if work == 1:
t = Thread(target=self.work_1)
t.start()
else:
t = Thread(target=self.work_2)
t.start()
@staticmethod
def work_1():
print ('Work 1 started')
# Do some Task and return a list
sleep(1)
mb.showinfo("test", "Work 1 complete")
@staticmethod
def work_2():
print ('Work 2 Started')
# Do some Task and return a list
sleep(1)
mb.showinfo("test", "Work 2 complete")
if __name__ == '__main__':
root = tk.Tk()
run_gui = SmallGui(root)
root.mainloop()
更新:
无论出于何种原因,我的上述解决方案在python 3中工作,但在2.7.14中没有。
但是下面的例子在2.7.14中有用,应该适合你。
我在这里做的是创建2个类属性来监视每个线程。 我创建了一个方法,如果线程处于活动状态,将检查1秒钟,如果线程变为非活动状态,则会弹出消息框。
from threading import Thread
from time import sleep
import Tkinter as tk
import tkMessageBox as mb
import ttk
class SmallGui(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.master.title('test gui')
self.button_1 = ttk.Button(self.master,
text='Start 1',
command=lambda: self.init_thread(1))
self.button_2 = ttk.Button(self.master,
text='Start 2',
command=lambda: self.init_thread(2))
self.button_1.pack()
self.button_2.pack()
self.work1_status = None
self.work2_status = None
def init_thread(self, work):
if work == 1:
self.work1_status = Thread(target=self.work_1)
self.work1_status.start()
self.check_thread(self.work1_status, work)
else:
self.work2_status = Thread(target=self.work_2)
self.work2_status.start()
self.check_thread(self.work2_status, work)
def check_thread(self, pass_thread, thread_name):
if pass_thread.isAlive() == False:
pass_thread = None
mb.showinfo("test", "Work {} complete".format(thread_name))
else:
self.after(1000, lambda: self.check_thread(pass_thread, thread_name))
@staticmethod
def work_1():
print ('Work 1 started')
# Do some Task and return a list
sleep(5)
@staticmethod
def work_2():
print ('Work 2 Started')
# Do some Task and return a list
sleep(5)
if __name__ == '__main__':
root = tk.Tk()
run_gui = SmallGui(root)
root.mainloop()