Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 销毁线程中的顶级会锁定根_Python_Multithreading_Tkinter_Python 3.3_Python Multithreading - Fatal编程技术网

Python 销毁线程中的顶级会锁定根

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

我有一个我一直在写的程序,它是一个助手函数,我可以根据报告中的一些信息查找共享驱动器上的某个报告。我决定给它一个GUI,这样我就可以把它分发给其他员工,在我第一次尝试实现
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您可以添加一个答案来证明这一点,以便我可以接受它吗?这就是我经过大量研究和反复试验后提出的解决方案。