Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tkinter 3.0 multiple keyboard events together

2,541 views
Skip to first unread message

Pavel Kosina

unread,
Dec 25, 2008, 11:52:52 PM12/25/08
to pytho...@python.org
Is it possible to catch in an event more that one key from keyboard? In
my code, I can handle always the only one, the first I press, the others
are omitted. Say, I press both "4" and "8" and only "4" is catched.

def movePlayer(event):
print (event.keysym)


Thank you.

--
geon
Pavel Kosina

janislaw

unread,
Dec 26, 2008, 5:09:04 AM12/26/08
to

Each keypress triggers another event. Fortunately there are two types
of events: reaction to press and release. The logic to write to
recognize those as simultaneous clicks is up to you :)

JW

Pavel Kosina

unread,
Dec 26, 2008, 11:44:08 AM12/26/08
to janislaw, pytho...@python.org
janislaw napsal(a):

> On 26 Gru, 05:52, Pavel Kosina <g...@post.cz> wrote:
>
>> Is it possible to catch in an event more that one key from keyboard? In
>> my code, I can handle always the only one, the first I press, the others
>> are omitted. Say, I press both "4" and "8" and only "4" is catched.
>>
>> def movePlayer(event):
>> print (event.keysym)
>>
> Each keypress triggers another event. Fortunately there are two types
> of events: reaction to press and release. The logic to write to
> recognize those as simultaneous clicks is up to you :)
>

Might you give me a little bit more? Just a link to a site where this is
explained and showed would be OK. I really did my best but everything is
bad.

geon

janislaw

unread,
Dec 27, 2008, 6:38:31 AM12/27/08
to

Use google to find the appropriate site, or browse this site, there
are plenty of examples. You may want to examine the code I wrote to
you to catch the idea:
#----------------------
import Tkinter
import pprint

tk = Tkinter.Tk()
f = Tkinter.Frame(tk, width=100, height=100)
msg = Tkinter.StringVar()
msg.set('Hello')
l = Tkinter.Label(f, textvariable=msg)
l.pack()
f.pack()

keys = set()

def keyPressHandler(event):
keys.add(event.char)
display()

def keyReleaseHandler(event):
keys.remove(event.char)
display()

def display():
msg.set(str(keys))

f.bind_all('<KeyPress>', keyPressHandler)
f.bind_all('<KeyRelease>', keyReleaseHandler)

f.mainloop()
#----------------

Regards,
JW

Pavel Kosina

unread,
Dec 27, 2008, 9:08:24 AM12/27/08
to janislaw, pytho...@python.org
janislaw napsal(a):

Is this really the most simple solution how to do this in Tkinter? Is
there nothing cleaner "build inside"?

This solution has disadvantage that after you release one key, that the
function keyPressHandler stopped to be called by the other pressed keys.
I would have not to build moving the player in KeyPresshandler, but on
another new function that would have to read periodically "keys" and to
act afterwards....

I really tried to search for words mentioned in this subject, but
nothing, not even this solution, was found by me.

PK


janislaw

unread,
Dec 27, 2008, 3:51:37 PM12/27/08
to

Um, I could be only guessing what are you meant to do, unless you
describe your problem in more detailed way. I.e. describe the desired
behaviour, show code which you have, and describe the current
behaviour.

> This solution has disadvantage that after you release one key, that the
> function keyPressHandler stopped to be called by the other pressed keys.
> I would have not to build moving the player in KeyPresshandler, but on
> another new function that would have to read periodically "keys" and to
> act afterwards....

Hmmm. Maybe you'd like to hook into Tkinter event loop, i.e. by custom
events if you don't like periodical polling.

From what I am guessing, you expect that 2 keyboard events are
simultaneous and can be cached at the same time instant. Well that
would be impossible, cause all the underlying hardware is sequential.
You may have parallel stuff if you go down to VHDL and write your own
hardware, but when you have a CPU, then you'll have to stick with
writing programs. C'mon, 20 lines is not such a big deal.

Regards
JW

Pavel Kosina

unread,
Dec 28, 2008, 3:43:20 AM12/28/08
to janislaw, pytho...@python.org
janislaw napsal(a):

> Um, I could be only guessing what are you meant to do, unless you
> describe your problem in more detailed way. I.e. describe the desired
> behaviour, show code which you have, and describe the current
> behaviour.
>
>

well, I am working on a tutorial for youngster (thats why i need to stay
the code as easy as possible). In this game you are hunted by robots. I
could use key"7" on numeric keypad for left-up moving but seems to me,
that "4"+"8" is much more standard for them.


>> This solution has disadvantage that after you release one key, that the
>> function keyPressHandler stopped to be called by the other pressed keys.
>> I would have not to build moving the player in KeyPresshandler, but on
>> another new function that would have to read periodically "keys" and to
>> act afterwards....
>>
>
> Hmmm. Maybe you'd like to hook into Tkinter event loop, i.e. by custom
> events if you don't like periodical polling.
>

No, that would be even more difficult. I already have a code that use
your idea:

from Tkinter import *
root = Tk()

pressedKeys=set()

def onKeyPress(event):
pressedKeys.add(event.keysym)

def onKeyRelease(event):
pressedKeys.remove(event.keysym)

def move():
print list(pressedKeys)
root.after(100,move)

root.bind("<KeyPress>", onKeyPress)
root.bind("<KeyRelease>", onKeyRelease)
root.after(100,move)
root.mainloop()


well, I thought that gui´s have such a problem already built-in - so
that i am not pressed to code it. You know, its not exactly about me -
if I do it for myself, for my program, that there is no problem, but I
need to explained it to begginners ..... And I do not want, as might be
more usual, do my module, that would cover this "insanity" (look at it
with 13-years old boy eyes ;-) ). Do you like to say me, that this is
not a standard "function" neither in tkinter, not say gtk or the others,
too?

I would expect something like this:

def onKeyTouch(event):
print (event.keysymAll)

root.bind("<KeyPress>", onKeyTouch)

and all the pressed keys are printed ....all the functions OnKeyPress,
OnKeyRelease, move, even set pressedKeys are in onKeyTouch....


P.

janislaw

unread,
Dec 28, 2008, 3:34:04 PM12/28/08
to
On 28 Gru, 09:43, Pavel Kosina <g...@post.cz> wrote:
> well, I am working on a tutorial for youngster (thats why i need to stay
> the code as easy as possible). In this game you are hunted by robots. I
> could use key"7" on numeric keypad for left-up moving but seems to me,
> that "4"+"8" is much more standard for them.
>

Ok, I get it then! Your goal is very humble :)

In the piece of code we have came together to, there is a
functionality you already want - the pressedKeys. I suppose, that
you'd like to hide from the further implementors (children). You can
write another module, which could contain this piece of code and could
be imported by kids to have the desired features.

Meaning only getting this list of keys.

But what you write here:

> I would expect something like this:
>
> def onKeyTouch(event):
>     print (event.keysymAll)
>
> root.bind("<KeyPress>", onKeyTouch)

...is a bit misleading. There is no such thing as simultaneous events
- for that the event dispatcher loop is designed - to simplyfy all
usual
stuff with parallel paradigsm such as interrupts, thread safety
etc. An event is in my eyes a response to a short action, let's call
it
atomic. There's no need to pretend, that clicking a few keys
simultanously is sth immediate and the software could by any chance
guess that a few keys were actually clicked. Even the keyboard driver
does some sequential scanning on the keys, and the key codes are then
send to the board sequentially as well. Try to run this code:

#----------------
#Tkinter multiple keypress
#Answer http://groups.google.com/group/comp.lang.python/browse_thread/thread/88788c3b0b0d51d1/c4b7efe2d71bda93
import Tkinter
import pprint
import time

tk = Tkinter.Tk()
f = Tkinter.Frame(tk, width=100, height=100)
msg = Tkinter.StringVar()
msg.set('Hello')
l = Tkinter.Label(f, textvariable=msg)
l.pack()
f.pack()

keys = set()

lastTime = None

def keyPressHandler(event):
keys.add(event.char)
global lastTime
now = time.time()
if lastTime:
difference = now - lastTime
if difference < 0.1: #seconds
print difference, 's'
lastTime = now
display()

def keyReleaseHandler(event):
keys.remove(event.char)
display()

def display():
msg.set(str(keys))

f.bind_all('<KeyPress>', keyPressHandler)
f.bind_all('<KeyRelease>', keyReleaseHandler)

f.mainloop()
#--------------------------------


... and find out, how 'simultaneous' they are. For me it's 0.0,
meaning that the event handlers were executed one after another, but
sometimes there is sth like 0.0309998989105 s - proabably an USB
latency, or an operating system context switch - hard to tell.

If you'd like to have two key clicks to generate a single event, you'd
have to write some timeout code (threading.Timer or tk stuff is handy)
to check how 'simultaneous' they actually were. Search web for events
in <<doubled>> inequality signs if you really want this.

I don't know gtk, but hey, pygame has pygame.key.get_pressed if you'd
like to switch:

http://www.pygame.org/docs/ref/key.html

Have luck
Jan

Gabriel Genellina

unread,
Dec 29, 2008, 12:40:41 AM12/29/08
to pytho...@python.org
En Sun, 28 Dec 2008 06:43:20 -0200, Pavel Kosina <ge...@post.cz> escribió:

> well, I am working on a tutorial for youngster (thats why i need to stay
> the code as easy as possible). In this game you are hunted by robots. I
> could use key"7" on numeric keypad for left-up moving but seems to me,
> that "4"+"8" is much more standard for them.

> [...]


> well, I thought that gui´s have such a problem already built-in - so
> that i am not pressed to code it. You know, its not exactly about me -
> if I do it for myself, for my program, that there is no problem, but I
> need to explained it to begginners ..... And I do not want, as might be
> more usual, do my module, that would cover this "insanity" (look at it
> with 13-years old boy eyes ;-) ). Do you like to say me, that this is
> not a standard "function" neither in tkinter, not say gtk or the others,
> too?

I don't recall any application that handles simultaneous keystrokes.
Multiple keystrokes are handled at the library level, but only with regard
to the "modifier" keys (shift, control, alt), so the application sees
Control-P as a *single* synthesized event instead of four.
I'm afraid you'll have to roll your own logic, as your use case isn't very
common. Perhaps treat "4" followed by "8" in quick succession the same as
a fictional event "48" equivalent to "7".

--
Gabriel Genellina

0 new messages