[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Problems with events and keys



Charles Christie wrote:
Oh wait, what I was thinking for was something completely different. I actually have no clue on how to restrict the textsprite class to only accept letters, numbers and keypad strokes simply and cleanly. I could just go and make a looooooong if/else statement that either has all the keys I want or all the keys I don't want to respond to... either way looks really long and painful >.<

Please let me rephrase my question: Is there a clean way to make my program only accept letters, numbers and number pad input and ignore everything else?

I'll try to explain the process i went through to do this.
Okay. First thing i think when i want to solve this problem is 'what is in the event object that might help us with this?'
so i write the following script:


#DisplayKeydownEvents.py
import pygame
from pygame.locals import *
pygame.display.init()
screen = pygame.display.set_mode((640,480))

while 1:
pygame.display.update()
screen.fill((0,0,0),(0,0,640,480))
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
raise SystemExit
else:
print event
#------------------------
by pressing the various keys i see thai the event object has a key called 'unicode' that contains the letter that i pressed.


The name 'unicode' seems to imply that the function may sometimes not have a unicode and instead have a utf-8 or whatnot as its key, but a quick search of pygame.org's documents reveals that

   KEYDOWN	     unicode, key, mod

So now we know that we can check the 'unicode' attribute.

So in order to only get alphabetical items:

if event.type == KEYDOWN:
   if event.unicode.isalpha():
      print event.unicode

Ok we got that working. Now for the numpad.
Unfortunately, there's not an 'isNumpad' function so let's examine the events again.
By pressing the various numpad buttons we find their keycode is sequential.
There are two ways to go about it.
One way is, assuming you're using just the numpad digits and not the +, -, etc...
is to realize that numpad 0 is 256 and numpad 9 is 265.
Obviously anything in this range will include the other numbers.
Another thing to notice: if the number is in this range, we can mod it by 256, to get the number value.
So:
elif 256 <= event.key <= 265:
print event.key % 256


As you can see, we don't deal with the events in your actual class, we just don't pass anything to your textsprite unless it's something we want to display.

We'd also like to check for number inputs. fortunately we see that the unicode value contains the actual number.
Hmm. what kind of methods do strings have to help us with this?
>>> dir('a')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__str__', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'replace', 'rfind', 'rindex', 'rjust', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']


Ah, okay. two methods interest us: isdigit and isalnum.
we can either add another elif clause or modify our original. Modifying the original is easier.
So it becomes:
if event.type == KEYDOWN:
if event.unicode.isalnum():
print event.unicode


Cool side effects that we get:
if they're holding shift then the unicode value will be capitalized so we don't have to deal with the shift key.
the numpad key values are the same whether or not numlock is on. if this is a side effect you don't want you can check the event's 'mod' attribute. This is essentially a flag, but for some reason they use large values. 2**13 for numlock, 2**14 for capslock, and they're adding the values together.
Basically this means if event.mod == 4096 or event.mod == 12288 numlock is down.


I thought it would help you more if you had the rationale behind the code.
I hope this helps you.
Final code is attached.
-Luke


import pygame
from pygame.locals import *
pygame.display.init()
screen = pygame.display.set_mode((640,480))

while 1:
    pygame.display.update()
    screen.fill((0,0,0),(0,0,640,480))
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                pygame.quit()
                raise SystemExit
            elif event.unicode.isalnum():
                print event.unicode
            elif 256 <= event.key <= 265:
                print event.key % 256
            else:
                print event