2015-02-12 92 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