Python GUI: Event Binding with Tkinter

·

3 min read

Python GUI: Event Binding with Tkinter

I'm a visual learner, so the first thing I always learn is some kind of GUI (if available). Tkinter is an obvious choice for Python.

The first thing I recommend to beginners, is to learn how to update GUI components from each other. Mostly this is done by callback-functions, e.g. when defining a button you can already define what's happening when pressed using a command-parameter:

def callback_func():
    print("clicked!")

btn = Button(root, text="Click me!", command=callback_func)
btn.pack()

Very easy, very nice. At some point though, you'll want to do something when text is entered or when a label is clicked or maybe create a menu when a right click is executed on the window frame.

This is where learning a GUI gets really interesting because for the most part every GUI framework does this a little different.

For Tkinter, since not every widget supports callbacks or command-Parameters, we use EventBinding to bind an event to a function within the context of a GUI component/widget.

Let's start from the top with a skeleton program and some basic elements - namely a textfield (Entry) and a label:

from tkinter import *

root = Tk()

ent = Entry(root)
ent.pack()

lbl = Label(root, text="input something ..", bg="green")
lbl.pack()

root.mainloop()

Really basic and really simple. If you run this script, a window will pop up and have exactly the widgets we wanted. Note: creating the label with green background isn't really required but Tkinter can't really deal very well with MacOS dark mode.

Now, just before the mainloop(), let's add the EventBinding and then explain it afterwards:

# binding callback function
def bcallback(event):
    print(event)

# binding
ent.bind('<Key>', bcallback)

The context for our EventBinding is the Textfield/Entry widget. We're binding an event <Key> to a function bcallback. If you run this script, and observe the console output, you'll see something like this:

tkinter_KeyEvent.png

That information is useful if you need any of the parameters, but let's go for something else and update the Label widget with the contens of the Entry widget:

# binding callback
def bcallback(event):
    lbl['text'] = ent.get()

# binding
ent.bind('<Key>', bcallback)

If you run this, you will notice something interesting:

tkinter_KeyEvent_lbl1.png

The reason for this is we're using the <Key> event that fires as soon as we press the key. At this point in time the text isn't entered in the Entry yet. It just happens too fast for us to really notice.

To resolve this issue, simply use the <KeyRelease> event:

# binding callback
def bcallback(event):
    lbl['text'] = ent.get()

# binding
ent.bind('<KeyRelease>', bcallback)

The result:

tkinter_KeyEvent_lbl2.png

Well, there you go. That's really all there is to it and it's a great place to start to learn more about widgets and events. For Tkinter in particular there's lots of events available as well as modifiers, virtual events and more. Check here for a more comprehensive list.