2015-02-12 85 views
1

我在某些網站上發現了與我的問題類似的以下代碼。每當我按下用戶界面上的按鈕,它都會掛起。請幫我解決這個問題。用戶界面上的按鈕掛起

import Tkinter 
from Tkinter import * 
import Tkinter as tk 
import time 

class simpleapp_tk(Tkinter.Tk): 
    def __init__(self,parent): 
     Tkinter.Tk.__init__(self,parent) 
     self.parent = parent 
     self.initialize() 

    def initialize(self): 
     self.grid() 


     button = Tkinter.Button(self,text=u"Click me !", 
           command=self.OnButtonClick) 
     button.grid(column=1,row=0) 


     self.grid_columnconfigure(0,weight=1) 
     self.resizable(True,False) 

    def OnButtonClick(self): 
     for i in range(10): 
      print 'deep' 
      time.sleep(1) 

    def OnPressEnter(self,event): 
     self.labelVariable.set("You pressed enter !") 

if __name__ == "__main__": 
    app = simpleapp_tk(None) 
    app.title('my application') 
    app.mainloop() 
+0

你能分享任何日誌嗎? – aberna 2015-02-12 06:43:28

+0

整個調試代碼在這裏。如果你可以運行,你可以很容易地看到在打印過程中掛着的「Click Me」按鈕 – 2015-02-12 06:46:09

回答

1

我相信你是這樣的財產以後後:

import Tkinter 
import time 

class simpleapp_tk(Tkinter.Tk): 
    def __init__(self,parent): 
     Tkinter.Tk.__init__(self,parent) 
     self.parent = parent 
     self.initialize() 

    def initialize(self): 
     self.grid() 


     button = Tkinter.Button(self,text=u"Click me !", 
           command=self.OnButtonClick) 
     button.grid(column=1,row=0) 


     self.grid_columnconfigure(0,weight=1) 
     self.resizable(True,False) 

     self.i = 0; #<- make counter 

    def OnButtonClick(self):    
     print 'deep' 
     self.i += 1; 
     if self.i==10: return #<1-- stop if we hit 10 iterations 
     self.after(1000, self.OnButtonClick) #<- use this 


    def OnPressEnter(self,event): 
     self.labelVariable.set("You pressed enter !") 

if __name__ == "__main__": 
    app = simpleapp_tk(None) 
    app.title('my application') 
    app.mainloop() 

請看看的顯着變化。基本上,它更好地使用after方法在給定時間做某事,而不是阻止整個tk窗口。因此,如果你想要執行某些東西10次,只需要保留計數器self.i並使用self.after方法調用OnButtonClick

作爲替代方案,您可以將循環放入單獨的線程中。例如:

import Tkinter 
import time 

import threading 

class simpleapp_tk(Tkinter.Tk): 
    def __init__(self,parent): 
     Tkinter.Tk.__init__(self,parent) 
     self.parent = parent 
     self.initialize() 

    def initialize(self): 
     self.grid() 


     button = Tkinter.Button(self,text=u"Click me !", 
           command=self.OnButtonClick) 
     button.grid(column=1,row=0) 


     self.grid_columnconfigure(0,weight=1) 
     self.resizable(True,False) 

     # define a thread, but dont start it yet. 
     # start it when button is pressed. 
     self.t = threading.Thread(target=self.do_in_loop) 

    def do_in_loop(self): 
     # this will be executed in a separate thread. 
     for i in range(10): 
      print i, 'deep' 
      time.sleep(1) 

    def OnButtonClick(self): 
     # start the thread with the loop 
     # so that it does not block the tk. 
     if not self.t.isAlive(): 
      self.t.start() 


    def OnPressEnter(self,event): 
     self.labelVariable.set("You pressed enter !") 

if __name__ == "__main__": 
    app = simpleapp_tk(None) 
    app.title('my application') 
    app.mainloop() 
+0

感謝Marcin,它有幫助,但根據我的要求,我想要禁用UI按鈕,直到函數OnButtonClick '正在完成它的工作,一旦函數完成,那麼只需要從UI請求另一個請求 – 2015-02-12 07:31:18

+0

我在下次單擊按鈕時遇到以下線程代碼錯誤:Tkinter回調中的異常 Traceback(最近一次調用的最後一個) : 返回self.func(* args) 文件「C:/Users/deekumar/Desktop/tim.py」中的文件「C:\ Python27 \ lib \ lib-tk \ Tkinter.py」,行1486,__call__中的 「 ,第38行,OnButtonClick self.t.start() 文件「C:\ Python27 \ lib \ threading.py」,第739行,開頭 raise RuntimeError() 「線程只能啓動一次」) RuntimeError:線程只能啓動一次 – 2015-02-12 08:52:51

+0

它意味着它說什麼。你可以多次啓動一個[線程](http://stackoverflow.com/questions/14293368/restarting-thread-in-python-why-needs-the-instance-to-be-recreated)。你需要製作新的主題。 – Marcin 2015-02-12 08:59:05