Effective Keyboard Input Handling

What is a good way to implement keyboard handling? In any language, where I write a keyboard-interactive program (such as a tetris game), I end up having some code that looks like this:

for event in pygame.event.get():
    if event.type == KEYDOWN:
        if False: pass          #make everything an elif
        elif rotating: pass
        elif event.key == K_q:
        elif event.key == K_e:
        elif event.key == K_LEFT:
            curpiece.shift(-1, 0)
            shadowpiece = curpiece.clone(); setupshadow(shadowpiece)
        elif event.key == K_RIGHT:
            curpiece.shift(1, 0)
            shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

(shortened). I don't like this, as this has to go in my main loop, and it messes with all parts of the program. This also makes it impossible to have a user config screen where they can change which key maps to which action. Is there a good pattern to do this using some form of function callbacks?


Asked by: Elise333 | Posted: 24-09-2021






Answer 1

You could create a dictionary where the keys are the input and the value is a function that handles the keypress:

def handle_quit():
  quit()

def handle_left():
    curpiece.shift(-1, 0)
    shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

def handle_right():
    curpiece.shift(1, 0)
    shadowpiece = curpiece.clone(); setupshadow(shadowpiece)

def handle_pause():
    if not paused:
        paused = True

branch = {
  K_q: handle_quit
  K_e: handle_pause
  K_LEFT: handle_left
  K_RIGHT: handle_right
}

for event in pygame.event.get():
    if event.type == KEYDOWN:
        branch[event.key]()

Then changing the keys is a matter of modifying keys of the dictionary.

Answered by: Lyndon350 | Posted: 25-10-2021



Answer 2

in addition to superjoe30's answer, you can use two levels of mapping (two dictionaries)

  • key => command string
  • command string => function

I think this would make it easier to allow user-defined mappings. i.e. so users can map their keys to "commands" rather than "the name of a function"

Answered by: Rafael234 | Posted: 25-10-2021



Answer 3

What I do nowadays is have some sort of input gathering class/function/thread which will check a list of predefined key->event bindings.

Something like this:

class InputHandler:
    def __init__ (self, eventDispatcher):
        self.keys = {}
        self.eventDispatcher = eventDispatcher
    def add_key_binding (self, key, event):
        self.keys.update((key, event,))
    def gather_input (self):
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                event = self.keys.get(event.key, None)
                if not event is None:
                    self.eventDispatcher.dispatch(event)

....
inputHandler = InputHandler(EventDispatcher)
inputHandler.add_key_binding(K_q, "quit_event")
...
inputHandler.gather_input()
....

It's basically what superjoe30 is doing, except that instead of calling callbacks directly, I add another level of separation by using an event dispatching system, so that any code that cares about the keys being pressed simply listen for that event.

Also, keys can be easily bound to different events, which could be read from a config file or something and any key which is not bound to an event is simply ignored.

Answered by: Marcus226 | Posted: 25-10-2021



Similar questions

Is there an effective way to hide an inline keyboard with python telegram bot?

I am developing a python telegram bot app, and need to close or hide an inline keyboard with a set of InlineKeyboardButton, once the user clicks on one of them, because if any button is clicked later, my app is not in the same context and the response is not appropriate. I did not find a comprehensive way to make this. I saw how it can be done with custom keyboards and one time use parameter. How could I handle thi...


python - How to make a cost effective but scalable site?

Portal Technology Assessment in which we will be creating a placement portal for the campuses and industry to help place students. The portal will handle large volumes of data and people logging in, approximately 1000 users/day in a concurrent mode. What technology should i use? PHP with CakePHP as a framework, Ruby on Rails, ASP.NET, Python, or should I opt for cloud computing? Which of those are the most cost ben...


file - effective use of python shutil copy2

if we take a look at a file copy function, we can see there are several exceptions to handle. A good example is here: http://msdn.microsoft.com/en-us/library/9706cfs5.aspx my question is if i use python shutil copy2, what should I pay attention to cope with various exceptions (source file not found, access not authorized, etc.)? ...


replace - Python: Effective replacing of substring

I have code like this: def escape_query(query): special_chars = ['\\','+','-','&&','||','!','(',')','{','}','[',']', '^','"','~','*','?',':'] for character in special_chars: query = query.replace(character, '\\%s' % character) return query This function should escape all occurrences of every substring (Notice && and


python - Effective way to find total number of files in a directory

I am building a Music file organizer(in python2) in which I read the metadata of all files & then put those file in the required folder. Now, I am already ready with the command line interface but this script shows feedback in a way that it shows "Which file is it working on right now?". If the directory contains say 5000 mp3 files, there should be some kind of feedback. So, I wou...


Simple and effective solution for combining Java, Python, PyTables and HDF5

I'm a newbie in Python, PyTables and HDF5. I'm looking for simple and best solution for my problem. Problem is next. On one side I have many XML files with data. I just wanna parse these files and put data in hdf5 file on other side. Later, I will use this data trough some search criteria.Why HDF5? Because need to put large dataset and because speed. Using RDBMS will make problems with performance during JOIN oper...


filter - Python: most effective way of filtering a list

I hope I'm not duplicating here :-) I'm wondering what's the most effective way of filtering a python list. The task I have in hand is to find out list elements that are not appearing in some other list. My fist list is a list of objects (without unnecessary details): Class A: def __init__(self,item1, item2): self.item1 = item1 self.item2 = item2 later o...


python - what is the most effective way to find the modal values of a list?

to be able to work with bimodal lists etc. my attempts so far: testlist = [1,2,3,3,2,1,4,2,2,3,4,3,3,4,5,3,2,4,55,6,7,4,3,45,543,4,53,4,53,234] . from collections import Counter def modal_1(xs): cntr = Counter(xs).most_common() val,count = cntr[0] return (v for v,c in cntr if c is count) print(list(modal_1(testlist))) >>> [3, 4] ...


datetime - Python: Effective way to convert ambiguous hours into time object?

I have a list of strings as follows: 4:00-5:00PM 11:00-2:00PM 12:00-1:00PM 11:00-1:00AM and I'm trying to find an effective way to create two time objects (I suppose this is the only way to keep track of a range of time, which I will later combine with a date object). It is clear to humans what we mean we say 11:00-1:00AM, but wondering what's an effective way to convert this to:


Python: Effective storage of data in memory

I have the following dictionary structure ( 10,000 keys with values being formed by list of lists ) my_dic ={0: [[1,.65,3, 0, 5.5], [[4, .55, 3, 0, 5.5] ...(10,000th value)[3,.15, 2, 1, 2.5]], 1:[[1,.65,3, 0, 5.5], [[4, .55, 3, 0, 5.5] ...(10,000th value)[3,.15, 2, 1, 2.5]] ..... 10,000th key:[[1,.65,3, 0, 5.5], [[4, .55, 3, 0, 5.5] ...(10,000th value)[3,.15, 2, 1, 2.5]]} (Note: Da...


python - most effective way to parse with nltk

What the most effective way to parse with nltk? I have a big vocabulary and take me age to parse with RecursiveDescentParser. Thanks






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top