Erich Schmidt
Erich Schmidt

Reputation: 77

Simple bind function doesn't work in python

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:

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.

Upvotes: 0

Views: 1117

Answers (2)

Bryan Oakley
Bryan Oakley

Reputation: 385970

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

Upvotes: 1

Pythonista
Pythonista

Reputation: 11615

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.

Upvotes: 1

Related Questions