Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/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 Tkinter程序正在使用forget()崩溃_Python_Multithreading_Python 2.7_Crash_Tkinter - Fatal编程技术网

Python Tkinter程序正在使用forget()崩溃

Python Tkinter程序正在使用forget()崩溃,python,multithreading,python-2.7,crash,tkinter,Python,Multithreading,Python 2.7,Crash,Tkinter,在我的程序中,我想在按钮上使用“忘记”。现在如果我尝试,程序就会崩溃。我知道这与线程有关,但我还没有找到解决方案。提前谢谢。下面是我的示例代码: import Tkinter as tk import thread window = tk.Tk() def ok(): pass def voice(): button1.forget() print("If you see this, it works!") thread.start

在我的程序中,我想在按钮上使用“忘记”。现在如果我尝试,程序就会崩溃。我知道这与线程有关,但我还没有找到解决方案。提前谢谢。下面是我的示例代码:

import Tkinter as tk
import thread

window = tk.Tk()

def ok():
    pass

    def voice():
        button1.forget()
        print("If you see this, it works!")

    thread.start_new_thread(voice,())

button1=tk.Button(command=ok, text="PRESS")
button1.pack()

window.mainloop()

Tkinter因其缺乏线程安全性而臭名昭著,这意味着您编写的代码有时可以工作,有时会导致整个程序挂起而不产生错误,这是一种痛苦

幸运的是,Tkinter确实有自己的方法来处理这个问题,所以要启动一个包含语音的线程,只需调用语音。但是,在语音结束时,请确保您使用了window.after方法,以便稍后再次调用它。例如:

import Tkinter as tk
import thread

window = tk.Tk()

def ok():
    pass

    def voice():
        button1.forget()
        print("If you see this, it works!")
        window.after(10, voice())

    voice()

button1=tk.Button(command=ok, text="PRESS")
button1.pack()

window.mainloop(

除了创建对象的线程外,您不能从任何线程访问tkinter对象。换句话说,您不能从线程调用button1.forget并期望它可靠地工作


普遍接受的解决方案是让线程将信息写入线程安全队列,让GUI线程周期性地轮询该队列,拉出一个项目,并执行该项目请求的任何操作

因此,我使用mtTkinter模块简单地解决了这个问题,您可以在这里找到:
要使用它,您只需在开始时将import mtTkinter作为Tkinter编写。之后,您可以正常使用您的Tkinter。此模块不会更改Tkinter中的任何内容,只会使其对线程友好。

访问创建它的线程以外的线程中的小部件,往往会使Tkinter翻转并崩溃。为什么在这里使用线程呢?直接发出按钮的命令声音。@kevin好吧,这只是一个示例代码。在我的实际程序中,我使用pyttsx,为此我需要线程。也许你可以重构你的代码,使所有特定于Tkinter的操作都在主线程上进行。例如,voice将全局应忘设置为True,root有一个after_idle回调方法,该方法定期检查应忘是否为True,并根据需要调用forget。原始问题不会在计时器上运行任何内容,所以我不认为添加计时器能解决任何问题。他发布了希望利用多线程和tkinter的代码,这是完全不可能的。我冒昧地假设他的最终目标是让某些东西与主线程同时运行,否则使用线程有什么意义呢。我发布的解决方案提供了他可能需要的所有信息,但他决定实施他的计划。这取决于他如何使用它。那么我能做些什么来回避这个问题呢?@Duardo:我已经稍微更新了我的答案。如果您搜索此网站,则有此解决方案的示例。