tkinter 3.0 multiple keyboard events together

P

Pavel Kosina

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.
 
J

janislaw

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.

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
 
P

Pavel Kosina

janislaw napsal(a):
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
 
J

janislaw

janislaw napsal(a):



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

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
 
P

Pavel Kosina

janislaw napsal(a):
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()

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
 
J

janislaw

janislaw napsal(a):








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

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
 
P

Pavel Kosina

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.
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.
 
J

janislaw

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.


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?

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...read/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
 
G

Gabriel Genellina

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".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top