Reputation: 45
No! Not to a function, but to the button's specified "command" option at any specific moment in the program. I have a code block where the button changes it's function and appearance but I want the Enter key to be bound to it, no matter the function it calls. There are points in the program where the button is disabled, but binding the enter key to it still activates the function, even though the button's disabled. There has to be a way to do that, or a way around it. Maybe there's a way to simulate the button-click event somehow. I just can't believe there's no direct way to do this. The only alternative I see at the moment is to keep binding and unbinding for every function and button. It just seems so un-pythonic.
Upvotes: 2
Views: 2039
Reputation: 385830
If your binding calls the invoke
method of the button, then it will do nothing when the button is disabled. If the button is enabled, it will do whatever the button is designed to do. Of course, you could also just bind to a function that checks the state of the button before doing anything.
Here's a contrived example. It contains a button labelled "Count" which increments a counter and updates the display. There are two other buttons used to enable or disable this first button.
Once the window has focus, if you press the return key it will invoke the button. Notice that after you disable the button the return key does nothing. When you re-enable the button the return key works again.
import tkinter as tk
COUNT = 0
def count():
global COUNT
COUNT += 1
label.configure(text=f"Count: {COUNT}")
root = tk.Tk()
label = tk.Label(root, text="Count: 0")
button = tk.Button(root, text="Count", command=count)
enable_btn = tk.Button(root, text="Enable Count", command=lambda: button.configure(state="normal"))
disable_btn = tk.Button(root, text="Disable Count", command=lambda: button.configure(state="disabled"))
label.pack(side="top", fill="x", pady=20)
button.pack(side="left", padx=(0,10))
disable_btn.pack(side="right")
enable_btn.pack(side="right")
root.bind_all("<Return>", lambda event: button.invoke())
root.mainloop()
Upvotes: 1
Reputation: 745
A button's command can be invoked as
btn = tkinter.Button(command=lambda: print("Hello!"), text="Press me for greeting")
btn.pack() # This is not required to allow invoke() to work
btn.invoke()
which calls the function. This works even if the button is not actually on-screen, as shown in the snippet.
However, it will not work if the button state is "disabled"
. I would recommend storing the function used in a separate variable in this case.
In the example below, the command for the button just calls a method belonging to the class. This means that you can call the function by pressing a button, or by calling the method directly, even if the button is disabled, hidden or deleted. The button simply looks at the current definition of the function and calls it.
import tkinter as tk
class Window(tk.Tk):
def __init__(self):
super().__init__()
self.bind("<Return>", lambda event: self.current_button_function())
self.btn = tk.Button(self, text="Press me!", command=lambda: self.current_button_function())
# command=self.current_button_function won't work since it won't update when the function updates
self.btn.pack()
self.mainloop()
def current_button_function(self):
print("This is a function. Button click is now disabled but function is still callable and enter still works")
self.btn.configure(state="disabled")
#self.current_button_function = lambda: print("This is simple lambda") # For easily returning single expression
def tmp(): # For a multi-line function
print("This is another function which works even though the button is disabled! The button is no longer on the page but the function is still callable and enter still works")
self.btn.forget()
def tmp():
print("The button is not on the page but it doesn't matter!")
#Could continue adding nested 'def' and/or 'lambda'
self.current_button_function = tmp
self.current_button_function = tmp
if __name__ == "__main__":
window = Window()
Try clicking the button and/or pressing enter a few times to see it change the callback function and still work even when the button is forgotten or disabled.
Upvotes: 0