Hello, in this tutorial, I am going to teach you how to use mouse and keyboard bindings to call an event that is not set with the “command” setting that we have been using so far in the other tutorials in this series. The issue that many people face is that once the program is in mainloop() it cannot be modified, and calls cannot be made to it. Bindings allow for a pre-prepared callback function to be made for a certain event. Following is a simple program that has a binding that prints the location of the “click” of a mouse.
#! /usr/bin/python # MouseClick.py - To demonstrate Tkinter key clicks import Tkinter class App: def __init__(self): # Set up the frame self.root = Tkinter.Tk() self.frame = Tkinter.Frame(self.root, width=100, height=100) # set up a mouse event self.frame.bind("<Button-1>", self.click) self.frame.pack() # Set Tkniter's main loop self.root.mainloop() def click(self, event): print("Clicked at: ", event.x, event.y) if __name__ == "__main__": App()
I am pretty sure that this code is explained well enough by comments, but at the command self.frame.bind the arguments are the type of event that is being monitored and the callback function, which only does what it is programmed to do when and only when the handler is triggered. That way, now, inside the mainloop, when a click is made the corresponding click function springs into action.
There are many different possible events, but here is just one more example program before we move on. This program shows the capabilities of multiple handlers at the same time.
#! /usr/bin/python # KeyPress.py - To demonstrate Tkinter key presses import Tkinter class App: def __init__(self): # Set up the frame self.root = Tkinter.Tk() self.frame = Tkinter.Frame(self.root, width=100, height=100) # set up a mouse event self.frame.bind("<Button-1>", self.click) self.frame.pack() # Now set up a key event! self.frame.bind("<Key>", self.key) self.frame.pack() # This call gives the frame focus so that it receives input. self.frame.focus_set() # Set Tkinter's main loop self.root.mainloop() def click(self, event): print("Clicked at: ", event.x, event.y) def key(self, event): # Make sure the frame is receiving input! self.frame.focus_force() print("Pressed", event.keysym) if __name__ == "__main__": App()
This program responds to clicks and keys. The necessity for setting focus initially is so that the user, in their hurry to run it, they don't have to click on it!
So now that you have seen two simple programs, it is time that we discussed the different types of events. At this point in the tutorial series, I will cover the basic events that you may encounter (which is pretty much all you need anyway).
- <Button-1> - This can also be <ButtonPress-1> of just <1>. This is an event that occurs when the Mouse button is pressed. The right mouse button is <Button-3> and the middle button is <Button-2>. The most widely accepted style is <Button-*> not the other derivatives.
- <B1-Motion> - This event is called when the mouse is dragged as the mouse button is held down. (Note: B2, B3 are also options as consistent with the event above).
- <ButtonRelease-1> - This is triggered when whatever mouse button is released. The last x and y coordinates of the mouse are relayed to the function.
- <Double-Button-1> - This is what happens when a widget is double clicked. (Notes: The word Triple can be used as well, and when a double click event is called, so is a single click event.
- <Enter> - This means that the mouse has entered the widget's area.
- <Leave> - This is called when the mouse leaves the widgets area
- <FocusIn> - This event is called when this component or a child component gets the user's focus.
- <FocusOut> - This event is called when this or a child component loses focus.
As if those mouse events weren't enough, there are actually more:
- <Return> - This event is called when the Enter key is pressed. “Return” can be placed with the name of any special key, such as F1 or Escape. The name of the keys can be found by using the second program that we build above (thought it was useless? Think again.)
- <Key> - This is called when the user presses any key. The actual key that was pressed is found in the member “char” in the event structure that is passed to the callback function.
- a – This important binding is called when the user types the key that is specified. However, it must be a key that when the program above is run, the result is a single key like 'a' and not like 'space'
- <Shift-Up> - This event is called when the user presses the Shift key and the up arrow. 'Shift' can be replaced by Alt and Control.
This next one is miscellaneous, but rather important so here goes:
- <Configure> - This event is called when the configuration of a widget is changed, such as when the frame changes size.
Now, these are all certain events that could happen during mainloop(). Next, let's examine the event structure that is passed to the callback. There are 9 main parts to it:
- x, y – This tells mouse position.
- x_root, y_root – These tell how far from the top-right corner of the screen you are.
- char – This returns a string containing the CHARACTER CODE pressed as a string.
- keysym – This tells the KEY SYMBOL, not the CODE or character code.
- keycode – This tells the current key code.
- num – This is the button number that influenced the action.
- width, height – After a resize is made, if a handler is set up for it, this is the new size for the frame.
- type – This merely tells the type of event.
Right, now that you have these you can edit the programs that I gave you at the beginning of the tutorial and edit it slightly to see the different outputs (try to replace 'keysym' with 'char' or 'keycode') just so that when you must develop a full application, you have the ability to do so.
Finally, there are 3 more things I must discuss. There are 3 types of binding, instance binding, class binding, and TopLevel bindings.
The only difference is on what scale the binding refers (such as a Text widget instead of anywhere). The bind keyword sets a binding onto whatever component and only that one. The bind_class keyword is unrecommended, as it re-binds the standard bindings that Python sets up. Finally, the bind_all keyword bind the binding to an entire application.
I hope that part was clear.
If you have questions, feel free to ask and I'll try to help if I can.