Keyboard and Mouse Events


We've got something that works, more or less -- but its interface is still a bit unwieldy. It would be nice if we could use the mouse and keyboard to make things a bit more intuitive. When you're running the Tk main loop, hitting a key on the keyboard or moving the mouse around generates events, which you can bind to callback functions in a similar way to when a button is pressed. Let's take a look at how we could make the text box respond to pressing Return rather than clicking the button. Now we've already got a function to handle that, the Button3 callback -- unfortunately we can't just use that since callbacks from events are different from buttons. We'll have to wrap it in another function:

def ReturnInsert(event):
	Button3()

Then we register this callback with the event we're looking for using the bind function:

text.bind("<Return>", ReturnInsert)

It's important here that we use the <Return> event code rather than the <Enter> event code, since the second triggers when the mouse enters the listbox. Now say we want to let the user use right click to remove items from the listbox, it's pretty much the same process. First we write a callback that accepts the event as input:

def DeleteCurrent(event):
	listbox.delete(ANCHOR)	

Then we bind the event to this callback:

listbox.bind("<Double-Button-3>", DeleteCurrent)

The right mouse button is called Button-3 in Tk (not to be confused with the name of our third form button callback), since the second mouse button refers to middle click. Finally, let's allow the user to copy a note back to the text box, in case they want to modify it. We don't have a function that allows this yet, so we'll have to write some new code in the callback:

def CopyToText(event):
	text.delete(0,END)
	current_note = listbox.get(ANCHOR)
	text.insert(0, current_note)

Then bind the event to the callback like before:

listbox.bind("<Double-Button-1>", CopyToText)

That's all there is to it. You're not just limited to these events though, for a guide to which events you can bind, check out the Tkinter library introduction.

Now seems like a good time to clean up our program. Button1 is a poor name for a function -- we've already been tripped up by similar names once, let's not do it again. We'll also take this opportunity to change some of the button effects, as it makes more sense for the Enter button to be closest to the text box for example, and Button1 isn't particularly useful, so let's get rid of it. No real changes to functionality, but the program now looks like this:

#!/usr/bin/python

from Tkinter import *

root = Tk()
root.geometry("600x400")
root.title("Note Taker")

def Enter():
	text_contents = text.get()
	listbox.insert(END, text_contents)
	text.delete(0,END)

def Remove():
	listbox.delete(ANCHOR)	

def Save():
	pass

def ReturnInsert(event):
	Enter()

def DeleteCurrent(event):
	Remove()

def CopyToText(event):
	text.delete(0, END)
	current_note = listbox.get(ANCHOR)
	text.insert(0, current_note)

textframe = Frame(root)
listframe = Frame(root)

enter_button = Button(textframe, text="Enter", command = Enter)
remove_button = Button(textframe, text="Remove", command = Remove)
save_button = Button(textframe, text="Save", command = Save)

text = Entry(textframe)

scrollbar = Scrollbar(listframe, orient=VERTICAL)
listbox = Listbox(listframe, yscrollcommand=scrollbar.set, selectmode=EXTENDED)
scrollbar.configure(command=listbox.yview)

text.bind("<Return>", ReturnInsert)
listbox.bind("<Double-Button-3>", DeleteCurrent)
listbox.bind("<Double-Button-1>", CopyToText)

text.pack(side=LEFT, fill=X, expand=1)
enter_button.pack(side=LEFT)
remove_button.pack(side=LEFT)
save_button.pack(side=LEFT)
listbox.pack(side=LEFT,fill=BOTH, expand=1)
scrollbar.pack(side=RIGHT, fill=Y)

textframe.pack(fill=X)
listframe.pack(fill=BOTH, expand=1)

root.mainloop()

Related links

Comments

1

kirti - 04/04/08

how can take the scrollbar in listview at top positon and right side

» Report offensive content

2

Erik Carlson - 12/05/08

Good write up.
I've been working with Python in scripting sql commands to recreate test customer databases in Oracle, but this is the first time I've found a cohesive and logical progression in understanding how to pull various widgets, packing and framing together in one write up. One problem I have with current documentation with Tk is no high level overview. I have one now.

Thanks,
Erik

» Report offensive content

3

Aimen Latir - 10/06/08

Nice report you have there.
I was trying to get all that into python, but when I ran the code, it said that I didn't have the module called "TKinter". May you please help me figure out where to get TK? I've been looking all over the internet, but I still can't find it.

Please help me,
Aimen

» Report offensive content

4

Nick - 04/08/08

This was a fantastic tutorial - one of the best I've found on the net to date about everything, it was concise and straight forward.

Just one thing I thought I should mention, when going through the first page I didn't realise I had to pack both the scrollbar and the listbox until I went though the code underneath the scrollbar section, maybe mention that.

» Report offensive content

5

Mike - 19/09/08

Aimen Latir,
make sure when you import you use "Tkinter" with only the t capitalized because the Python interpriter is case sensitive.

» Report offensive content

6

arkaros - 12/10/08

great tutorial two thumbs upp. Have you thought of making a folow up. I am thinking of maby learning abit of python to use with blender but you i gotta start somewhere because python is pretty different from the other languages i have used

» Report offensive content

7

jeremy - 17/10/08

how do you accept int values? doesnt the entry even convert everything to a string?

» Report offensive content

8

Joe - 18/02/09

I get this error when I try to add the buttons:

Traceback (most recent call last):
File "C:\Python26\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py", line 312, in RunScript
exec codeObject in __main__.__dict__
File "C:\Documents and Settings\jpattison\Desktop\test\test.py", line 6, in <module>
button1 = Button(root, text="button1")
File "C:\Python26\lib\lib-tk\Tkinter.py", line 2002, in __init__
Widget.__init__(self, master, 'button', cnf, kw)
File "C:\Python26\lib\lib-tk\Tkinter.py", line 1932, in __init__
(widgetName, self._w) + extra + self._options(cnf))
TclError: can't invoke "button" command: application has been destroyed

(sorry to take so much space!)

What could be the problem?
Thanks!

» Report offensive content

9

Mark Abajian - 12/03/09

Very helpful. Many thanks.

» Report offensive content

10

mark s - 23/03/09

Thanks for putting this into plain english, now ive got the basics i can start to understand the rest of tkinter. Well done on this concise and clear tutorial

» Report offensive content

11

Fabio - 27/04/09

Definitely one of the greatest tutorials ever! :D I love the spinn-off application I've built today using your tutorial. Thank you so much for the time you took to explain this as extensively as you did. You're the best! :D will certainly get deeper into Python and TK! :D

» Report offensive content

12

Fabio - 27/04/09

Definitely one of the greatest tutorials ever! :D I love the spinn-off application I've built today using your tutorial. Thank you so much for the time you took to explain this as extensively as you did. You're the best! :D will certainly get deeper into Python and TK! :D

» Report offensive content

13

Matt - 26/06/09

OMG this is THE BEST! I haven't found a single tutorial on this subject and it's been killing me tryin to find one! Thnx loads! This will definately help me loads!!!!!!!!!:D

» Report offensive content

14

Matt - 09/07/09

Joe,
It looks like an error with the Tkinter.py file. Maybe it's a version clash... What version of python have you got? Maybe this isn't going to work for 3.x . Maybe...i got that error once but i can't remember how i fixed it...try searching in your python directory for Tkinter and if there's a compiled python file for Tkinter try...deleting it. BE CAREFUL!!! DO NOT DELETE THE .py FILE. ONLY THE COMPILED PYTHON FILE IF THERE IS ONE!!!

» Report offensive content

15

Chris - 23/07/09

Thankyou so much for taking the time to write up this tutorial. I have looked at some much other documentation and all of it was garbage compared to the simple step by step method you use.

» Report offensive content

16

Shakir Ahmed - 30/07/09

It is really a great to startup but if I need more details to develop customize application where I will get that.

» Report offensive content

17

Gulam Gaus - 20/08/09

Its very good & descriptive help for Tkinter at times when there arent good practical documentation available anywhere & scarcity of such valuable input to all the budding developers..Good work. Keep it up. Maybe I expect to see more of such illustrative technical input for all developers.

» Report offensive content

18

Rat - 26/08/09

This isn't even right, learn how to program.

» Report offensive content

19

Rat - 26/08/09

Ha ha! JOSEPH! Look at me i like to steal people's computers

» Report offensive content

20

Rat - 26/08/09

21

Michael Jackson - 03/03/10

I am learning to program in Python but not new to programming. I am in search of answer and I've searched and searched the web not one website has anything that has to do with EVENTS such as OnCreate, OnShow, BeforeDestory, AfterDestroy, OnChange, OnFormCreate, etc...I've gone through a lots of examples all over the web but I am coming empty handed. Just a simple example would be so great.

Please help.

» Report offensive content

22

vj - 03/03/10

its a good one.............

» Report offensive content

Leave a comment

You must read and type the 6 chars within 0..9 and A..F

* indicates mandatory fields.

22

vj - 03/03/10

its a good one............. ... more

21

Michael Jackson - 03/03/10

I am learning to program in Python but not new to programming. I am in search of answer and I've searched ... more

20

Rat - 26/08/09

Errrr mikaela ... more

Log in


Sign up | Forgot your password?

What's on?

  • Optus Deal

    Broadband + home phone + PlayStation®3 in a single package price!