GUI Python with Tkinter – Part 6 – Events and callbacks

Widgets should be responsive to events (pressing of buttons or keys, mouse clicks etc). This requires associating callbacks with specific events. Callbacks are associated with events, which is known as command binding.

Command binding is the simplest way to add functionality to a button.

command = some_callback

The command is available only for certain widgets.

If we have the following function …

def callback1():
	# do something when button is clicked

… then we can link it to a button with the command option:

Button(root, text = "Click me", command = callback1)

The callback1 is called by Button() which takes the callback1 as a parameter. The callback1 is passed without parentheses because a reference is passed to a function.

Note:
If parentheses are added then the function will be called when the program runs. We need the callback only when an event occurs.

If a callback needs to take arguments, we can use the lambda function:

def callback2(argument)
	#do something with argument

The Button with a command callback that takes arguments:

Button(root, text = "Click", command = lambda: callback2('some argument'))

Note:
By default, the command button binds to the left-click and the space bar. It does not bind to the return key; very counter-intuitive.

Tkinter’s bind() – a more intuitive way to deal with events.

The standard syntax is widget.bind(event, handler, add = None).

Example:

from tkinter import *
root = Tk()

Label(root, text = 'Click in the blue frame').pack()

def callback1(event1):
	print(dir(event1))
	print('Clicked at', event1.x, event1.y)

frame1 = Frame(root, bg = 'white', width = 150, height = 100)
frame1.bind('', callback1)
frame1.pack()

root.mainloop()

If you run the code in the terminal you will get something like shown below:

Tkinter events and callbacks

When clicking somewhere within the white frame the terminal will print something like shown below:

ddn_ro@Linux:~/Documents/TKINTER$ python3 test07.py
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', 
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'char', 'delta', 'height', 'keycode', 'keysym', 
'keysym_num', 'num', 'send_event', 'serial', 'state', 'time', 'type', 'widget', 'width', 'x', 
'x_root', 'y', 'y_root']
Clicked at 80 62

The Frame widget is binded to the event (left-click … it is a buit-in event in Tkinter). When this event occurs, it calls the callback1 function.

We define the callback1(event1) function.
We inspect the event object by using dir(event1) (returns a list of attribute names for the event object passed to it). The event1.x and event1.y are part of the list and we used them to print the coordinates of the point of click.

Here are a couple of event pattern examples similar to Button-1:

  • – A keyboard press of Alt + Ctrl + Delete
  • – A keyboard press of B key

An event pattern usually contains:

  • An event type – Button, ButtonRelease, KeyRelease, Keypress, FocusIn, FocusOut, Leave, MouseWheel, etc.
  • An event modifier (optional) – Alt, Any, Control, Double, Lock, Shift, etc.
  • The event detail (optional) – The mouse event detail is captured by the number 1 for a left-click and the number 2 for a right-click; each key press on the keyboard is either represented by the key letter itself (B in ) or by using a key symbol abbreviated as keysym (up arrow key on the keyboard is represented by the keysym value of KP_Up.

There are three levels of binding:

  • Instance-level binding – bind an event to an instance of a widget (the previous example).
  • Application-level binding – use the same binding across all windows and widgets of an application.
  • Class-level binding – used to set the same behavior for all instances of a particular widget class.

You need variables with a wide variety of widgets. You might need a string variables to track what the users enter into entry widgets or text widget or Boolean variables to track whether users has checked off the Checkbox widget or integer variables to track the value entered in a Spinbox or Slider widget, and so on.

Tkinter offers its own variable class which you can use to track widget-specific values. It must be subclassed from this Tkinter variable class. Few of the commonly used predefined variables are: StringVar, IntVar, BooleanVar, and DoubleVar.

You can also define your own variable type by calling the constructor:

my_string = StringVar()
ticked_yes = BooleanVar()
group_choice = IntVar()
volume = DoubleVar()

Tkinter also provides access to the values of variables via the set() and get() methods:

my_var.set("Value of my_var") # setting value of variable
my_var.get() # Assessing the value of variable from a callback, for example

Leave a Reply