0

I'm currently creating an adventure game and I want to bind alt+a to my callback. It doesn't do what I want, so I have two questions:

  • Is it possible to bind a function to a Label, too?
  • Why does this (simplyfied) code doesn't work?

Here is the code:

import tkinter as tk

dw = tk.Tk()
dw.title('Hearts')

def play(event):
    print('This is the test.')

areal = tk.Frame(master=dw, width=1200, height=600, bg='blue')
areal.pack_propagate(0)
areal.pack(fill=tk.BOTH, expand=bool(dw))
areal.bind("<Alt-A>", play)

dw.mainloop()

It doesn't give me an error, but it doesn't do anything when I click the Frame and afterwards press alt+a. What is wrong here?

EDIT:

import tkinter as tk

def go_fwd(event):
    areal.focus_set()
    print(event.x, event.y)

dw = tk.Tk()
dw.title('Adventure')


areal = tk.Frame(master=dw, width=20000, height=600, bg='blue')
areal.pack_propagate(0)
areal.pack(fill=tk.BOTH, expand=bool(dw)-100)
areal.focus_set()
dw.bind("<Alt-A>", go_fwd)

enter = tk.Frame(master=dw, width=20000, height=100, bg='cyan')
enter.pack(fill=tk.X)

enterentry = tk.Text(master=enter, width=100, height=4, bg='white')
enterentry.pack()
enterbutton = tk.Button(master=enter, text='Senden', bg='red')
enterbutton.pack()

dw.mainloop()

Here is the complete code.

Erich Schmidt
  • 67
  • 1
  • 1
  • 8

2 Answers2

1

You need to bind to dw instead of your frame.

So, you can do dw.bind("<Alt-A>", play).

A minor note, Alt-A will bind to the uppercase A as expected, so you'd have to click Alt+Shift+A on your keyboard. Doing Alt+A on your keyboard won't work, you'd have to bind to Alt-a for this to work.

The main window has keyboard focus. Or, alternatively you can leave the bind on the frame and just do areal.focus_set() to set the focus to the frame.

Pythonista
  • 11,377
  • 2
  • 31
  • 50
  • But why does it work fine with left-click and not with alt+a – Erich Schmidt Apr 15 '16 at 16:37
  • @ErichSchmidt: key events go to the widget that has focus. Button events go to the widget under the cursor. That's why the binding for a button seems to behave differently than the binding for a key. – Bryan Oakley Apr 15 '16 at 16:41
  • @BryanOakley: How do I execute my callback with a key? – Erich Schmidt Apr 15 '16 at 16:42
  • @ErichSchmidt: follow the instructions in this answer. Either give focus to the widget with the binding, or put the binding on a widget with focus. By default, clicking on a frame does not give it focus, so a third solution is to add another binding to the frame that sets the focus when it is clicked on. – Bryan Oakley Apr 15 '16 at 16:44
1

Is it possible to bind a function to a Label, too?

You can bind to any widget you want. However, if you bind key events, the bindings will only work if the widget has focus. By default, most widgets other than Entry and Text don't get focus unless you explicitly set the focus to them.

Note: only one widget can have keyboard focus at a time.

You can also set a binding to the root window, which will cause it to fire no matter what widget has focus.

For a more thorough explanation of how key bindings are processed, see this answer: https://stackoverflow.com/a/11542200/7432

Why does this (simplyfied) code doesn't work?

It doesn't work the way you expect because the binding is on a Frame widget, but that widget doesn't have the keyboard focus. You could give it focus with something like this:

areal.focus_set()

Or, you could only give it focus after you click on the frame, by creating a binding on a mouse click:

areal.bind("<1>", lambda event: areal.focus_set())

Note: you are binding to a capital "A", so make sure when you test that you're pressing control-alt-a

Community
  • 1
  • 1
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685