2014-12-05 85 views
0

在我的程序中,我想在按鈕上使用forget()。現在,如果我嘗試,程序崩潰。我知道它與線程有關,但我還是找不到靈魂。提前致謝。這裏是我的examplecode:Python 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_new_thread(voice,()) 

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

window.mainloop() 
+0

在創建它的線程之外的線程中訪問小部件往往會使Tkinter翻轉並崩潰。爲什麼在這裏使用線程?直接使用Button的命令'voice'即可。 – Kevin 2014-12-05 17:22:32

+0

@kevin嗯,這只是一個示例代碼。在我真正的程序中,我使用pyttsx,爲此我需要線程。 – Duardo 2014-12-05 17:31:03

+0

也許你可以重構你的代碼,以便所有的Tkinter特定的動作發生在主線程上。例如,語音將全局'should_forget'設置爲True,並且根具有'after_idle'回調方法,該方法定期檢查'should_forget'是否變爲True,並且適當地調用'forget'。 – Kevin 2014-12-05 17:33:28

回答

0

所以我簡單地通過使用模塊mtTkinter,你可以在這裏找到解決了這個問題。之後,你可以正常使用你的Tkinter。這個模塊在Tkinter中沒有任何變化,它只是使它對線程友好。

-1

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(
+0

原來的問題不會在計時器上運行任何東西,所以我不認爲增加計時器可以解決任何問題。 – 2014-12-05 20:37:06

+0

他發佈了想要使用多線程和tkinter的代碼,這是完全不可能的。我冒昧地假設他的最終目標是讓主題與主線程同時運行,否則使用線程有什麼意義。我發佈的解決方案提供了他可能需要的所有信息,但他決定實施他的計劃。他決定如何使用它。 – 2014-12-06 02:54:54

0

您不能從任何線程訪問tkinter對象,而是創建該對象的線程。換句話說,你不能從線程調用button1.forget(),並期望它可靠地工作。

普遍接受的解決方案是讓您的線程將信息寫入線程安全隊列,讓您的GUI線程在週期性輪詢該隊列,關閉某個項目並執行該項目所請求的任何操作。 http://tkinter.unpythonic.net/wiki/mtTkinter要使用它,你只需要在開始寫import mtTkinter as Tkinter

+0

那麼我能做些什麼來解決這個問題? – Duardo 2014-12-07 17:53:02

+0

@Duardo:我已經稍微更新了我的答案。如果你搜索這個網站,有這個解決方案的例子。 – 2014-12-07 18:23:55