1

I found the following code on some website which is similar to my problem . Whenever i press buttons on the user interface , it hangs . Please help me in fixing this .

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()
Deepak Kumar
  • 109
  • 1
  • 1
  • 12

1 Answers1

1

I believe you are after somthing like this:

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

Please have a look at marked changes. Basically, its better to use after method do do something at given time and not to block whole tk window. Thus if you want something to be executed 10 times, just make some veriable to hold the counter self.i and call OnButtonClick using self.after method.

As an alternative, you can put the loop into a separate thread. For example:

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()
Marcin
  • 215,873
  • 14
  • 235
  • 294
  • Thanks Marcin , it helps . But as per my requirement , i want the UI buttons to be disabled as well till the function 'OnButtonClick' is doing its job . Once the function finishes then only i want to request another request from UI. – Deepak Kumar Feb 12 '15 at 07:31
  • I am getting following error in thread code when i click the button next time: Exception in Tkinter callback Traceback (most recent call last): File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__ return self.func(*args) File "C:/Users/deekumar/Desktop/tim.py", line 38, in OnButtonClick self.t.start() File "C:\Python27\lib\threading.py", line 739, in start raise RuntimeError("threads can only be started once") RuntimeError: threads can only be started once – Deepak Kumar Feb 12 '15 at 08:52
  • It means what it says. You can start a same [thread multiple times](http://stackoverflow.com/questions/14293368/restarting-thread-in-python-why-needs-the-instance-to-be-recreated). You need to make new threads. – Marcin Feb 12 '15 at 08:59
  • I got it . Thanks for the reference . – Deepak Kumar Feb 12 '15 at 12:13