Python 销毁线程中的顶级会锁定根
我有一个我一直在写的程序,它是一个助手函数,我可以根据报告中的一些信息查找共享驱动器上的某个报告。我决定给它一个GUI,这样我就可以把它分发给其他员工,在我第一次尝试实现Python 销毁线程中的顶级会锁定根,python,multithreading,tkinter,python-3.3,python-multithreading,Python,Multithreading,Tkinter,Python 3.3,Python Multithreading,我有一个我一直在写的程序,它是一个助手函数,我可以根据报告中的一些信息查找共享驱动器上的某个报告。我决定给它一个GUI,这样我就可以把它分发给其他员工,在我第一次尝试实现tkinter和threading时遇到了几个错误 我知道一句古老的格言“我有一个问题,然后我使用线程,现在我有两个问题。”线程至少解决了第一个问题——现在转到第二个 我的淡化代码是: class GetReport(threading.Thread): def __init__(self,root):
tkinter
和threading
时遇到了几个错误
我知道一句古老的格言“我有一个问题,然后我使用线程,现在我有两个问题。”线程至少解决了第一个问题——现在转到第二个
我的淡化代码是:
class GetReport(threading.Thread):
def __init__(self,root):
threading.Thread.__init__(self)
# this is just a hack to get the StringVar in the new thread, HELP!
self.date = root.getvar('date')
self.store = root.getvar('store')
self.report = root.getvar('report')
# this is just a hack to get the StringVar in the new thread, HELP!
self.top = Toplevel(root)
ttk.Label(self.top,text="Fooing the Bars into Bazes").pack()
self.top.withdraw()
def run(self):
self.top.deiconify()
# a function call that takes a long time
self.top.destroy() #this crashes the program
def main():
root = Tk()
date,store,report = StringVar(),StringVar(),StringVar()
#####
## labels and Entries go here that define and modify those StringVar
#####
def launchThread(rpt):
report.set(rpt)
# this is just a hack to get the StringVar in the new thread, HELP!
root.setvar('date',date.get())
root.setvar('store',store.get())
root.setvar('report',report.get())
# this is just a hack to get the StringVar in the new thread, HELP!
reportgetter = GetReport(root)
reportgetter.start()
ttk.Button(root,text="Lottery Summary",
command=lambda: launchThread('L')).grid(row=1,column=3)
root.mainloop()
我的预期输出是让root
打开并填充标签、条目和按钮(本例中隐藏了一些)。每个按钮将从条目中提取数据,并将其发送到启动线程
功能,该功能将创建一个新线程,以执行获取我需要的文书工作所需的foos和bar
该线程将启动一个顶层,基本上只是通知用户它正在处理它。完成后,Toplevel将关闭,我请求的文书工作将打开(我正在使用ShellExecute
打开一个.pdf),同时线程退出(因为它退出了run
函数)
实际上,线程将启动其顶层,文件将打开,然后Python将变得无响应,需要“最终处理”。据我所知,您不能使用线程来更改任何GUI元素。例如破坏顶层窗口
任何Tkinter代码都需要在程序的主循环中执行。Tkinter不能接受来自主线程以外的线程的任何命令,因此在线程中启动
TopLevel
会因设计而失败,因为它无法访问另一个线程中的Tk
。要解决这个问题,请使用线程的.is\u alive
方法
def GetReport(threading.Thread):
def __init__(self,text):
self.text = text
super().__init__()
def run(self):
# do some stuff that takes a long time
# to the text you're given as input
def main():
root = Tk()
text = StringVar()
def callbackFunc(text):
top = Toplevel(root)
ttk.Label(top,text="I'm working here!").pack()
thread = GetReport(text)
thread.start()
while thread.is_alive():
root.update() # this keeps the GUI updating
top.destroy() # only when thread dies.
e_text = ttk.Entry(root,textvariable=text).pack()
ttk.Button(root,text="Frobnicate!",
command = lambda: callbackFunc(text.get())).pack()
嗨,詹姆斯。这是我一个月前提出的一个问题——从那时起我就解决了这个问题,但显然我忽略了发布答案!让我去看看我的代码,记住我到底做了什么。我有一个类似的问题,刚刚得到解决。它可能对你有帮助,也可能没有帮助,但它就在这里。谢谢你的帮助。我的问题用下面的代码解决了,而
之后的对我来说并不太好,因为我的代码可能需要不同的时间才能完成。不过我很感激你的想法!这不是一个好的解决方案。您在事件循环中添加了一个无限循环,这几乎总是应该避免的。相反,您可以设置一个动画循环,每隔一秒左右运行一次,以检查线程是否处于活动状态。@BryanOakley您可以添加一个答案来证明这一点,以便我可以接受它吗?这就是我经过大量研究和反复试验后提出的解决方案。