Generating events

When generating a custom event, we first need to name it in a way Tkinter will recognize. We can name an event anything we want (assuming it is not already reserved), as long as we enclose it between two less-than and greater-than signs, for example <<custom_event>>.

We can emit this event whenever we like by using the event_generate method of a Tkinter widget. The first argument to this widget will be our custom name, and the remaining keyword arguments will define some properties which will be sent to the handler via the usual event object.

To receive and handle this event, the bind method is used just like before.

Let's have a go at an example program which uses custom events:

import random
import tkinter as tk

win = tk.Tk()
sv = tk.StringVar()
sv.set('You are walking around with an open wallet...')
lab = tk.Label(win, textvar=sv)

Our program will feature a main window, a StringVar, and a Label. It tells the story of the user walking with an open wallet. They will both drop and find money. Since this is only a demo program, there's no need to try and keep track of total money. The amounts dropped and picked up are merely for demonstration.

We now need a couple of functions which will act as event handlers to display each gain or loss of money:

def user_found_money(event):
amount = event.x
sv.set('You found £' + str(amount))


def user_lost_money(event):
amount = event.x
sv.set('You dropped £' + str(amount))

Each function updates the value of our StringVar to show how much money was picked up or dropped. This will be sent to the event handler by the event x attribute (since we cannot define arbitrary attributes):

lab.pack(padx=50, pady=50)

win.bind("<<Find>>", user_found_money)
win.bind("<<Lose>>", user_lost_money)

Our Label is packed and we bind the window to two custom events. These are named <<Find>> and <<Lose>> to fit in with Tkinter's demand for event name formatting. Each time one of these events is emitted, we will call the appropriate function to update the StringVar and show the user how much money was found or lost:

def emit_custom_event():
choices = ['find', 'lose']
choice = random.choice(choices)

if choice == 'find':
win.event_generate("<<Find>>", x=random.randint(0, 50))
else:
win.event_generate("<<Lose>>", x=random.randint(0, 50))

win.after(2000, emit_custom_event)

win.after(2000, emit_custom_event)

win.mainloop()

A function to emit these events is defined as emit_custom_event. We use the random module to choose between a find or a lose string, then generate the relevant event using event_generate. We pass the necessary custom event name as the first argument and a random number to be stored in the x attribute of the event object which will be given to the handling functions.

Tkinter's after method is used to call the emit_custom_event function after 2 seconds, and the function will call itself every 2 seconds after that. This means the user will find or drop a random amount of money every 2 seconds while the application is open.

We finish up by calling mainloop to ensure our window displays when the program is run.

Run this program and watch as you find and lose money, all handled by our custom event objects.

With that, we now know how to create and listen for events within Tkinter. We can use this knowledge to build additional features into our basic text editor.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset