What I am trying to do is to set the button status to DISABLED whenever the textbox is empty. I recreated a snippet of my code bellow:
import tkinter
from tkinter import *
root = tkinter.Tk()
textbox = tkinter.Text(root, height=4)
textbox.pack()
button = tkinter.Button(text="Button", height=2, width=20, state=ACTIVE)
button.pack()
def check_if_textbox_is_empty():
if textbox.get("1.0", tkinter.END) == "":
return True
def if_textbox_is_empty():
button["state"] = DISABLED
# Here is the .bind method I tried, but since it doesn't take func as the first arg it doesn't work for me.
# root.bind(check_if_textbox_is_empty, if_textbox_is_empty)
root.mainloop()
How should go about doing this?
What I want to happen is, when my tkinter.Text has no text in it textbox.get("1.0", tkinter.END) == ""
I want my button widget to be disabled button["state"] = DISABLED
.
What I have tried is the .bind
method, but it seems that it only takes tkinter events ex.:"<Keypress>"
as an argument.
CodePudding user response:
Based on correct @JRiggles answer
Only when I added .strip()
in if textbox.get("1.0", tkinter.END).strip() == "":
button started change state.
import tkinter as tk
root = tk.Tk()
textbox = tk.Text(root, height=4)
textbox.pack()
button = tk.Button(text="Button", height=2, width=20, state=tk.ACTIVE)
button.pack()
def on_textbox_change(_event=None):
if textbox.get("1.0", tk.END).strip() == "":
button["state"] = tk.DISABLED
else:
button["state"] = tk.NORMAL
textbox.bind('<KeyRelease>', on_textbox_change)
root.mainloop()
CodePudding user response:
Firstly: You don't need both
import tkinter
and
from tkinter import *
Common practice is
import tkinter as tk
after which you can instantiate widgets like so (note how the constant for the state is also prefixed with tk.
- these constants are, as you may have guessed, part of tkinter)
button = tk.Button(text="Button", height=2, width=20, state=tk.ACTIVE)
However, just stick with import tkinter
for now
With that out of the way...
Why not simply enable/disable the button within the if
clause of check_if_textbox_is_empty()
? You can bind the '<KeyRelease>'
event to your text box and have it call the check function.
You have several options, all of which will work the same way in the end.
Option 1
Add an _event
parameter to the check_if_textbox_is_empty
function.
The leading underscore _
is convention to let people know that the value is unused by the function, and event
is the conventional name for the event argument taken by event-driven functions in tkinter. The default value of None
isn't strictly necessary, but it's good practice.
def check_if_textbox_is_empty(_event = None):
if textbox.get("1.0", tkinter.END) == "":
button["state"] = tkinter.DISABLED
else:
button["state"] = tkinter.NORMAL
# bind an event handler to your textbox to check it as the user types
textbox.bind('<KeyRelease>', check_if_textbox_is_empty)
Option 2
Use *_args
in your function to allow it to accept any number of arguments.
Again, the _
is convention for unused values, and args
is convention for this type of parameter
def check_if_textbox_is_empty(*_args): # accept any number of arguments
if textbox.get("1.0", tkinter.END) == "":
button["state"] = tkinter.DISABLED
else:
button["state"] = tkinter.NORMAL
# bind an event handler to your textbox to check it as the user types
textbox.bind('<KeyRelease>', check_if_textbox_is_empty)
Option 3
Use a lambda
to absorb the event and call check...
as an anonymous function
def check_if_textbox_is_empty(): # no params needed!
if textbox.get("1.0", tkinter.END) == "":
button["state"] = tkinter.DISABLED
else:
button["state"] = tkinter.NORMAL
# bind an event handler to your textbox to check it as the user types
textbox.bind('<KeyRelease>', lambda _event: check_if_textbox_is_empty())
Bonus Info!
The reason for adding the _event
parameter (or absorbing it with *_args
or using a lambda
) is that tkinter events typically generate an event
value when triggered, so your code has to be able to accommodate that value.
When you bind a function to an event and that event is triggered, the event
object gets passed to your function whether you want it or not!
There are plenty of reasons you might want your function to use the value of event
, but for this particular case you don't need it. You can use any of the methods described above to basically throw it out safely.