Now we can continue learning about Python by Binding Keys and Events.
If you have not read the previous article, then you definitely need to read it since this article continues and builds on all of it. Some of the following examples may contain material from the first article.
Mouse : MouseWheel
You need to use the 'MouseWheel' event on objects that can scroll. Let's look at an example where we have a global variable to keep count, called 'counter'. When you turn the wheel while the cursor is in the window, the counter goes up or down, depending on which way you turn the wheel.
It calculates the values to increase the number to 255. While the value is rising, the number changes the background color to match. The top label is for 'red', the second for 'green' and the bottom one for 'blue'. Once each value hits '255', then the next turn will change it to '0' and start counting up the next label. You should hopefully be able to follow the example since it is basically a counter.
If the value is 0 to 255, then it is for red. The values from 256 to 510 are for green, and the values from 511 to 765 are for blue. It places the values of the variables in a tuple and then sent through a converter to change the value appropriately for use.
You could just as easily change the values for specific objects and not just the window.
FocusIn and FocusOut
From the articles on Labels and Buttons you may remember that when an object gets Focus, the object will throw a ‘FocusIn’ event. When the focus leaves an object, we get a ‘FocusOut’ event.
The code will have four buttons. The focus starts on Button 1, and when you press the TAB key, the focus moves to Button 2. Once you press it again, the focus moves to Button 3 and triggers the ‘FocusIn’ event. Hit TAB again to go to Button 4, and Focus is lost for Button 3, causing the ‘FocusOut’ event to occur:
You can see that we are binding to a specific widget, ‘b3’.
Special Keys
This is basically a special key to perform key binding. There are a few special keys that can be bound using their names. The keys are:
I will insert the code to try your keyboard and see the output of keys being pressed. It lists the key name as ‘keysym’:
Just run the code, press a key and look for the output in the ‘terminal’ portion of the IDE.
Key Combinations
Similar to the ‘Special Keys’ section, this one has already had an example. This can be a combination of a modifier and key. If you use the above code, it does not show the combinations.
Give a few a try to see which work for you.
Configure
Python uses the event when a specified widget changes size, and on some Operating Systems it may occur when a widget moves.
Here is an example, but it triggers when the system draws the Button widget:
It could have a counter put on it to avoid the initial appearance of the Button and not print the message at count 1. Of course, it would then be a function and not a lambda.
Activate
This event occurs when a sub-window changes state. It sends the event to the top window.
Some events only work on certain Operating Systems. This is one of those events that I tried to get to work, but would not on Ubuntu. So, I forced the event to occur. This example code will have more details than necessary, but something you can see how it works to force an event:
The way this works to the user is that a window appears and has a button on it labeled ‘Make a new window’. When the user clicks it, a second window appears and has a button on it labeled ‘Destroy top window’. When the user clicks the new button, the second window disappears. The ‘activate’ event occurs when it creates the second window, and the ‘deactivate’ event happens when it destroys the second window.
Now, for the code. It creates the first window, called ‘root’, with one button, named ‘b1’. When clicked, it calls the function ‘show1’.
When you click on ‘show1’, it creates global variables for ‘root’ and ‘root1’ so it recognizes them in and out of the function. Next, we create the ‘root1’ window, create the button and place it in the window. The command ‘root1.grab_set’ is used to route all events to the ‘root1’ window. The last line for the unction is ‘root.event_generate("<Activate>")’. This is the line that throws the event ‘Activate’. You can force an event with this statement; just change the name of the event.
‘root1’, the second window, is visible and has a button that, when pressed, calls the ‘hide1’ function. For the ‘hide1’ function, it has three lines. The first line releases the ‘grab’ placed on it. While the next line ‘destroys’ the window and removes it from memory. Finally, the last line is the line that forces the ‘deactivate’ event.
You can see here how to create multiple windows, place widgets on those windows and throw events.
Destroy
This is the ability to remove a window from memory and make it disappear from the screen or an individual widget. If you destroy a window or widget, the ‘destroy’ event is called for each widget destroyed in the window and then again for the window itself.
The Destroy method will remove the object, but when it removes the object, it calls the Destroy Event:
Map
The Map Event occurs when it draws an object on the window. In the following example, pressing Button 1 will cause Button 2 to appear and trigger the '<Map>' event for Button 2 (b2).
Unmap
This event is the opposite of 'Map' and the system triggers it when it removes the bound object.
I'm hoping I don't need an example.
Visibility
the system triggers this event when the window is covered/uncovered or minimized/restored.
You will determine whether the window lost visibility because of another window being used, or if you minimize the window.
Circulate
When you open multiple programs, it assigns a window to each program. These windows are stacked one on each other. There is one top window that is visible to the user. If it reorders the stack of windows, then it triggers this event.
This can help maintain a window to remain on the top of the stack, or to know if the order was changed.
Conclusion
These are all the main key bindings and events used in Tkinter.
Be sure to try the code and understand how each works. Come up with your own tests to verify you understand how it works.
If you have not read the previous article, then you definitely need to read it since this article continues and builds on all of it. Some of the following examples may contain material from the first article.
Mouse : MouseWheel
You need to use the 'MouseWheel' event on objects that can scroll. Let's look at an example where we have a global variable to keep count, called 'counter'. When you turn the wheel while the cursor is in the window, the counter goes up or down, depending on which way you turn the wheel.
It calculates the values to increase the number to 255. While the value is rising, the number changes the background color to match. The top label is for 'red', the second for 'green' and the bottom one for 'blue'. Once each value hits '255', then the next turn will change it to '0' and start counting up the next label. You should hopefully be able to follow the example since it is basically a counter.
If the value is 0 to 255, then it is for red. The values from 256 to 510 are for green, and the values from 511 to 765 are for blue. It places the values of the variables in a tuple and then sent through a converter to change the value appropriately for use.
Code:
from tkinter import *
counter = 0
red1 = 0
green1 = 0
blue1 = 0
def _from_rgb(rgb):
r, g, b = rgb
return f'#{r:02x}{g:02x}{b:02x}'
def on_mousewheel(event):
global counter
global red1
global green1
global blue1
if event.num == 5: # mouse wheel up
counter -= 1
if (counter<0):
counter=765
if (counter<=255):
red1=counter
green1=0
blue1=0
if (counter<=510 and counter>255):
green1=counter - 255
red1=0
blue1=0
if (counter<=765 and counter>510):
blue1=counter - 510
red1=0
green1=0
l1.configure(text=red1)
l2.configure(text=green1)
l3.configure(text=blue1)
color_rgb = (red1, green1, blue1)
color1 = _from_rgb(color_rgb)
root.configure(bg=color1)
elif event.num == 4: # mouse wheel down
counter += 1
if (counter>765):
counter=0
if (counter<=255):
red1=counter
green1=0
blue1=0
if (counter<=510 and counter>255):
green1=counter-255
red1=0
blue1=0
if (counter<=765 and counter>510):
blue1=counter-510
red1=0
green1=0
l1.configure(text=red1)
l2.configure(text=green1)
l3.configure(text=blue1)
color_rgb = (red1, green1, blue1)
color1 = _from_rgb(color_rgb)
root.configure(bg=color1)
root = Tk()
root.title('Mouse Wheel Color')
root.geometry("400x800")
root.configure(bg="black")
for row in range(0,9):
root.grid_rowconfigure(row, weight=1)
for col in range(0,3):
root.grid_columnconfigure(col, weight=1)
l1 = Label(text="0")
l1.grid(column=1, row=0)
l2 = Label(text="0")
l2.grid(column=1, row=1)
l3 = Label(text="0")
l3.grid(column=1, row=2)
root.bind("<Button-4>", on_mousewheel) # wheel up
root.bind("<Button-5>", on_mousewheel) # wheel down
root.mainloop()
You could just as easily change the values for specific objects and not just the window.
FocusIn and FocusOut
From the articles on Labels and Buttons you may remember that when an object gets Focus, the object will throw a ‘FocusIn’ event. When the focus leaves an object, we get a ‘FocusOut’ event.
The code will have four buttons. The focus starts on Button 1, and when you press the TAB key, the focus moves to Button 2. Once you press it again, the focus moves to Button 3 and triggers the ‘FocusIn’ event. Hit TAB again to go to Button 4, and Focus is lost for Button 3, causing the ‘FocusOut’ event to occur:
Code:
from tkinter import *
root = Tk()
root.title('Button Binding FocusIn FocusOut')
root.geometry("400x800")
for row in range(0,9):
root.grid_rowconfigure(row, weight=1)
for col in range(0,3):
root.grid_columnconfigure(col, weight=1)
l1=Label(text='----')
l1.grid(row=7,column=1)
b1=Button(text='Button 1')
b2=Button(text='Button 2')
b3=Button(text='Button 3')
b4=Button(text='Button 4')
b1.grid(row=0,column=1)
b2.grid(row=2,column=1)
b3.grid(row=4,column=1)
b4.grid(row=6,column=1)
b3.bind('<FocusIn>',lambda event:l1.config(text='Focused Button 3'))
b3.bind('<FocusOut>',lambda event:l1.config(text='Focus Left Button 3'))
b1.focus_set()
root.mainloop()
You can see that we are binding to a specific widget, ‘b3’.
Special Keys
This is basically a special key to perform key binding. There are a few special keys that can be bound using their names. The keys are:
- Cancel (the Break key)
- BackSpace
- Tab
- Return(the Enter key)
- Shift_L or Shift_R
- Control_L or Control_R
- Alt_L or Alt_R
- Pause
- Caps_Lock
- Escape
- Prior (Page Up)
- Next (Page Down)
- End
- Home
- Left, Right, Up, Down
- Insert
- Delete
- F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12
- Num_Lock
- Scroll_Lock
I will insert the code to try your keyboard and see the output of keys being pressed. It lists the key name as ‘keysym’:
Code:
from tkinter import *
root = Tk()
def keyout(event):
print ('e.keysym: ',event.keysym,' e.keycode: ', event.keycode, 'e.keycode_num:', event.keysym_num,' e.state:',event.state)
print ('e.char: ',event.char,' e.type: ', event.type)
root.bind('<Key>', keyout)
root.mainloop()
Just run the code, press a key and look for the output in the ‘terminal’ portion of the IDE.
Key Combinations
Similar to the ‘Special Keys’ section, this one has already had an example. This can be a combination of a modifier and key. If you use the above code, it does not show the combinations.
Give a few a try to see which work for you.
Configure
Python uses the event when a specified widget changes size, and on some Operating Systems it may occur when a widget moves.
Here is an example, but it triggers when the system draws the Button widget:
Code:
from tkinter import *
def change():
b1.configure(height=3,width=30)
root = Tk()
root.title('Binding Button Configure')
root.geometry("400x800")
for row in range(0,9):
root.grid_rowconfigure(row, weight=1)
for col in range(0,3):
root.grid_columnconfigure(col, weight=1)
b1=Button(text="Button 1")
b1.grid(column=1, row=0)
b2=Button(text="Change 1",command=change)
b2.grid(column=1, row=1)
l1=Label(text=" ")
l1.grid(column=1, row=4)
l1.configure(text=" ")
b1.bind('<Configure>',lambda event:l1.config(text='Button 1 was changed!') )
root.mainloop()
It could have a counter put on it to avoid the initial appearance of the Button and not print the message at count 1. Of course, it would then be a function and not a lambda.
Activate
This event occurs when a sub-window changes state. It sends the event to the top window.
Some events only work on certain Operating Systems. This is one of those events that I tried to get to work, but would not on Ubuntu. So, I forced the event to occur. This example code will have more details than necessary, but something you can see how it works to force an event:
Code:
from tkinter import *
def hide1():
root1.grab_release()
root1.destroy()
root.event_generate("<Deactivate>")
def show1():
global root1, root
root1=Tk()
b2 = Button(root1,text="Destroy top window",command=hide1)
b2.grid(column=0, row=0)
root1.grab_set()
root.event_generate("<Activate>")
def on_activate(event):
print("Window activated")
def on_deactivate(event):
print("Window deactivated")
root = Tk()
b1 = Button(root,text="Make New window",command=show1)
b1.grid(column=0, row=0)
root.bind("<Activate>", on_activate)
root.bind("<Deactivate>", on_deactivate)
root.mainloop()
The way this works to the user is that a window appears and has a button on it labeled ‘Make a new window’. When the user clicks it, a second window appears and has a button on it labeled ‘Destroy top window’. When the user clicks the new button, the second window disappears. The ‘activate’ event occurs when it creates the second window, and the ‘deactivate’ event happens when it destroys the second window.
Now, for the code. It creates the first window, called ‘root’, with one button, named ‘b1’. When clicked, it calls the function ‘show1’.
When you click on ‘show1’, it creates global variables for ‘root’ and ‘root1’ so it recognizes them in and out of the function. Next, we create the ‘root1’ window, create the button and place it in the window. The command ‘root1.grab_set’ is used to route all events to the ‘root1’ window. The last line for the unction is ‘root.event_generate("<Activate>")’. This is the line that throws the event ‘Activate’. You can force an event with this statement; just change the name of the event.
‘root1’, the second window, is visible and has a button that, when pressed, calls the ‘hide1’ function. For the ‘hide1’ function, it has three lines. The first line releases the ‘grab’ placed on it. While the next line ‘destroys’ the window and removes it from memory. Finally, the last line is the line that forces the ‘deactivate’ event.
You can see here how to create multiple windows, place widgets on those windows and throw events.
Destroy
This is the ability to remove a window from memory and make it disappear from the screen or an individual widget. If you destroy a window or widget, the ‘destroy’ event is called for each widget destroyed in the window and then again for the window itself.
The Destroy method will remove the object, but when it removes the object, it calls the Destroy Event:
Code:
from tkinter import *
root = Tk()
root.title('Destroy Button')
root.geometry("400x800")
def Button_1():
b2.destroy()
def b2_gone(event):
l2.configure(text="Button Destroyed.")
for row in range(0,9):
root.grid_rowconfigure(row, weight=1)
for col in range(0,3):
root.grid_columnconfigure(col, weight=1)
l1 = Label(text="Press Button 1 to destroy Button 2.")
l2 = Label(text=" ")
b1 = Button(text="Button 1",command=Button_1)
b2 = Button(text="Button 2")
b1.grid(column=1, row=0)
b2.grid(column=1, row=2)
l1.grid(column=1, row=3)
l2.grid(column=1, row=4)
b2.bind("<Destroy>",b2_gone)
root.mainloop()
When you press Button 1, it causes the destruction of Button 2. When it destroys Button 2, it creates an event that is bound to 'b2' and calls the function 'b2_gone'.
Expose
If a window has been covered and now becomes ‘exposed’, it triggers this event.
In the following example, we place Button 2 (b2) over the top of Button 1 (b1). Once we click on Button 2, it destroys it and exposes Button 1. Once exposed, it calls the Destroy Event, which calls the 'b2_gone' function.
[code]from tkinter import *
def b2_gone():
b2.destroy()
l1.configure(text="Button 2 is gone.")
def exposed(event):
l2.configure(text="Button 1 is exposed.")
root = Tk()
root.title('Expose Button')
root.geometry("400x800")
for row in range(0,9):
root.grid_rowconfigure(row, weight=1)
for col in range(0,3):
root.grid_columnconfigure(col, weight=1)
count1 = 0
number = 0
l1 = Label(text=" ")
l2 = Label(text=" ")
b1 = Button(text="Button 1")
b2 = Button(text="Button 2",command=b2_gone)
b1.grid(column=1, row=0)
b2.grid(column=1, row=0)
l1.grid(column=1, row=3)
l2.grid(column=1, row=4)
b1.bind("<Expose>",exposed)
root.mainloop()
Map
The Map Event occurs when it draws an object on the window. In the following example, pressing Button 1 will cause Button 2 to appear and trigger the '<Map>' event for Button 2 (b2).
Code:
from tkinter import *
def b2_appear():
b2.grid(column=1, row=1)
def Appear(event):
l2.configure(text="Button 2 is now on the window.")
root = Tk()
root.title('Map Button')
root.geometry("400x800")
for row in range(0,9):
root.grid_rowconfigure(row, weight=1)
for col in range(0,3):
root.grid_columnconfigure(col, weight=1)
count1 = 0
number = 0
l1 = Label(text=" ")
l2 = Label(text=" ")
b1 = Button(text="Button 1",command=b2_appear)
b2 = Button(text="Button 2")
b1.grid(column=1, row=0)
l1.grid(column=1, row=3)
l2.grid(column=1, row=4)
b2.bind("<Map>",Appear)
root.mainloop()
Unmap
This event is the opposite of 'Map' and the system triggers it when it removes the bound object.
I'm hoping I don't need an example.
Visibility
the system triggers this event when the window is covered/uncovered or minimized/restored.
You will determine whether the window lost visibility because of another window being used, or if you minimize the window.
Circulate
When you open multiple programs, it assigns a window to each program. These windows are stacked one on each other. There is one top window that is visible to the user. If it reorders the stack of windows, then it triggers this event.
This can help maintain a window to remain on the top of the stack, or to know if the order was changed.
Conclusion
These are all the main key bindings and events used in Tkinter.
Be sure to try the code and understand how each works. Come up with your own tests to verify you understand how it works.

