1

I'm coding a game using python. I've used tkinter library. I want to bind w and a keys together how do I do this? I've tried using <w,a> , <w-a>, <w+a> and <KeyPress-w - KeyPress-a> but it just did not work. Any ideas?

My error:

Traceback (most recent call last):
  File "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\Zombie Surge\zombie surge.pyw", line 63, in <module>
    frame.bind('<w , a>',wa)
  File "C:\Users\DEVDHRITI\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1392, in bind
    return self._bind(('bind', self._w), sequence, func, add)
  File "C:\Users\DEVDHRITI\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1346, in _bind
    self.tk.call(what + (sequence, cmd))
_tkinter.TclError: extra characters after detail in binding
  • "it just did not work" is nothing we can work with. Post a [mre] (make sure it is minimal) and if you have an error message / stacktrace. – Patrick Artner Aug 17 '21 at 09:41
  • 1
    @PatrickArtner A minimal working example would be: `import tkinter as tk; root = tk.Tk(); root.bind(???, print); root.mainloop()` – TheLizzard Aug 17 '21 at 09:43
  • @TheLizzard exactly and then we could use that as root cause analisys. As well as the stacktrace. And that would help others immensly as they see what was the cause and would see the stacktrace and would make this more likely to not be closevoted and downvoted. – Patrick Artner Aug 17 '21 at 09:44
  • 1
    @PatrickArtner In this case there isn't really a need for a minimal working example/traceback. OP is asking just for 1 line of code. For anyone familiar with `tkinter`, just seeing the title should be enough to understand the problem. – TheLizzard Aug 17 '21 at 09:46
  • Yes, most people knowing Tk and how key binding is done there would know what's meant with the question. And still, an MWE would help to see what exactly was tried and where and how it failed. Finally, questions on SO are not only to help you who asked them but also to give others clues to their questions, and that's where every detail helps. Without that, you might as well delete the question after it's beeen answered... – Jeronimo Aug 17 '21 at 11:12
  • 1
    @Jeronimo OP said what they tried. And said that it didn't have the expected result. I think it's safe to assume that OP wants to bind to both `w` and `a` being pressed at the same time. The minimal working example is simple enough that anyone with `tkinter` experience can think of in a matter of seconds. I assume that people in the future that look at this question know what binds are and how to make a `tkinter` window. – TheLizzard Aug 17 '21 at 13:13

2 Answers2

1

Try this:

import tkinter as tk


keys_pressed = {"w": False,
                "a": False}

def pressed(event):
    if event.char in keys_pressed:
        keys_pressed[event.char] = True

def released(event):
    if event.char in keys_pressed:
        keys_pressed[event.char] = False

def loop():
    if keys_pressed["w"] and keys_pressed["a"]:
        print("W and A are pressed at the same time")
    elif keys_pressed["w"]:
        print("W is pressed")
    elif keys_pressed["a"]:
        print("A is pressed")
    root.after(100, loop)


root = tk.Tk()

root.bind("<KeyPress>", pressed)
root.bind("<KeyRelease>", released)

loop()

root.mainloop()

It uses a global dictionary to keep track of the keys pressed. And uses a tkinter loop to check if both of the keys are pressed at the same time.

TheLizzard
  • 7,248
  • 2
  • 11
  • 31
0

If you want to resolve a binding to a w followed by a you can do:

import tkinter as tk
root = tk.Tk()
root.bind(["w","a"], print) # as commented by @TheLizzard "wa" works as well
root.mainloop()

If you press any other key after 'w' this will not trigger - if you press 'w' followed by 'a' it will.

Pressing both simultaneously will lead to triggering - IF the tkinter registers the w key first.

Output if pressing 'w' followed by 'a' (or almost simultaneously):

<KeyPress event state=Mod1 keysym=a keycode=65 char='a' x=138 y=78>

Credit to https://stackoverflow.com/a/67559558/7505395:

Alternatively you could use the keyboard module and in the eventhandler of "w" also independently check if "a" is currently pressed:

import tkinter as tk
import keyboard 


def check(event):
    print(str(event))
    # evaluate the "a" key as well
    if keyboard.is_pressed("a"):
        print( "a pressed as well")

root = tk.Tk()
root.bind("w", check)  # will fire for every "w" pressed
root.mainloop()

This is not able to distinguish between "a (hold)" + "w" and "w (hold)" + "a" or smashing the whole area around w and a.

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • 1
    I don't think this is what OP wanted. Also instead of `["w", "a"]` you can just use `"wa"` – TheLizzard Aug 17 '21 at 10:01
  • it seems this only works once, the first time i press `w` and `a` it works and after that it moves in `w` or `a` direction –  Aug 17 '21 at 13:45