1

I want to disable tk inter button when executing command and enable it back once the command execution finished. I have tried this code, but it seems not working.

from Tkinter import *
import time

top = Tk()
def Run(object):
    object.config(state = 'disabled')
    print 'test'
    time.sleep(5)
    object.config(state = 'normal')

b1 = Button(top, text = 'RUN', command = lambda : Run(b1))
b1.pack()

top.mainloop()

The command execution run well, but every time I click the button when the command is being executed, 'test' appears in the console right after the Run function finished. Which mean the button is not disabled when the Run function is being executed. Any suggestion to fix this problem?

Thanks in advance

1
  • Using sleep as a placeholder for what you really want to do is a poor choice. sleep causes the whole gui to freeze. What are you really doing? A long calculation? A long database query? Commented Oct 29, 2014 at 22:34

3 Answers 3

1

I prefer to utilize Tkinter's "after" method, so other things can be done while the 5 seconds are counting down. In this case that is only the exit button.

from Tkinter import *
##import time
from functools import partial

top = Tk()

def Run(object):
    if object["state"] == "active":
        object["state"] = "disabled"
        object.after(5000, partial(Run, object))
    else:
        object["state"] = "active"
    print object["state"]

b1 = Button(top, text = 'RUN')
b1.pack()
## pass b1 to function after it has been created
b1["command"] = partial(Run, b1)
b1["state"]="active"

Button(top, text="Quit", command=top.quit).pack()

top.mainloop()
Sign up to request clarification or add additional context in comments.

1 Comment

But, I want to entirely disable the buttons so that no process occurs while the process on the run has not finished yet. For example if the button will show a window. If I use your code, I can show a multiple window which I don't want to happen
0

Use pack_forget() to disable and pack() to re-enable. This causes "pack" window manager to temporarily "forget" it has a button until you call pack again.

from Tkinter import *
import time

top = Tk()
def Run(object):
    object.pack_forget()
    print 'test'
    time.sleep(5)
    object.pack()

b1 = Button(top, text = 'RUN', command = lambda : Run(b1))
b1.pack()

top.mainloop()

1 Comment

Sleep simply freezes the tkinter instance. Do not use sleep in tkinter. Use after instead.
-2

You need

object.config(state = 'disabled')
b1.update()
time.sleep(5)
object.config(state = 'normal')
b1.update()

to update the button and pass execution back to Tkinter.

4 Comments

Thanks for the reply. Your code only works to disable the button. But I can still click the button (when it is disabled) and the command will be executed as soon as the previous command finished. It is like placing the command callback into a queue and run it once the previous command finished. I also don't know why. Actually, I manage to get it works using python multithreading. I use two threads, one for disabling the button and one for running the command. But I am still expecting a more simple solution.
Two threads sound good. One for the task. The mainloop should enable and disable the button.
In fact, sometimes Threading causes a problem that make the python program not responding with error message like this : TclError: bad state ":0.0": must be active, disabled, or normal
You must not access tkinter from any other thread that the main thread.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.