29

I am trying to bind the left and right arrow keys to an event in Tkinter, but when I run the program it appears the events are not triggering. Here is the code:

from Tkinter import *

main = Tk()

def leftKey(event):
    print "Left key pressed"

def rightKey(event):
    print "Right key pressed"

frame = Frame(main, width=100, height=100)
frame.bind('<Left>', leftKey)
frame.bind('<Right>', rightKey)
frame.pack()
frame.mainloop()

Why is this not working?

aftrumpet
  • 1,189
  • 2
  • 16
  • 28

4 Answers4

44

Try binding to your main variable:

from Tkinter import *

main = Tk()

def leftKey(event):
    print "Left key pressed"

def rightKey(event):
    print "Right key pressed"

frame = Frame(main, width=100, height=100)
main.bind('<Left>', leftKey)
main.bind('<Right>', rightKey)
frame.pack()
main.mainloop()

I should explain that this works because Tk is made aware of the bindings because the main window has keyboard focus. As @BryanOakley's answer explained you could also just set the keyboard focus to the other frame:

from Tkinter import *

main = Tk()

def leftKey(event):
    print "Left key pressed"

def rightKey(event):
    print "Right key pressed"

frame = Frame(main, width=100, height=100)
frame.bind('<Left>', leftKey)
frame.bind('<Right>', rightKey)
frame.focus_set()
frame.pack()
main.mainloop()

See more about events and bindings at effbot.

Also, you could also re-write this so your application is a sub-class of Tkinter.Frame like so:

import Tkinter


class Application(Tkinter.Frame):
    def __init__(self, master):
        Tkinter.Frame.__init__(self, master)
        self.master.minsize(width=100, height=100)
        self.master.config()

        self.master.bind('<Left>', self.left_key)
        self.master.bind('<Right>', self.right_key)

        self.main_frame = Tkinter.Frame()
        self.main_frame.pack(fill='both', expand=True)
        self.pack()

    @staticmethod
    def left_key(event):
        print event + " key pressed"

    @staticmethod
    def right_key(event):
        print event + " key pressed"

root = Tkinter.Tk()
app = Application(root)
app.mainloop()
Fiver
  • 9,909
  • 9
  • 43
  • 63
  • Great, glad to help! I've updated the answer with a version using a Frame sub-class for the application. Happy coding! – Fiver Nov 10 '13 at 22:54
  • 2
    The actual problem is simply that the frame doesn't have keyboard focus. If you set focus to the frame, the code in the question will work fine. – Bryan Oakley Nov 11 '13 at 03:29
  • @BryanOakley Thanks, I'll update the answer with this alternate solution. – Fiver Nov 11 '13 at 12:25
  • The important thing to keep in mind is to bind keys to the root frame/window, not to any nested frames (nor the widget displaying the shortcut). – Agi Hammerthief Nov 24 '16 at 13:39
26

The problem is simply that the frame you are binding to doesn't have the keyboard focus. When you press a key on the keyboard, the event is sent to the widget with the keyboard focus. By default, a frame does not have keyboard focus.

Add the following line to your code to move the keyboard focus to the frame:

frame.focus_set()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • 1
    +1 good point, I've updated the answer to include this solution. – Fiver Nov 11 '13 at 12:35
  • Does the parent of the widget with focus get the event if the widget does not have a listener for it? – Mad Physicist Mar 10 '21 at 10:34
  • @MadPhysicist: no. [this answer](https://stackoverflow.com/questions/11541262/basic-query-regarding-bindtags-in-tkinter/11542200#11542200) describes what happens. – Bryan Oakley Mar 10 '21 at 15:13
2
from tkinter import *


def leftKey(event):
    print("Left key pressed")


def rightKey(event):
    print("Right key pressed")


main = Tk()


frame = Frame(main, width=100, height=100)
main.bind('<Left>', leftKey)
main.bind('<Right>', rightKey)
frame.pack()
main.mainloop()
2

It might be that you don't intercept the right events. The arrows on the numeric keypad and the other ones have different symbolic names.

See http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/key-names.html

the ones on the numeric keypad are named with a 'KP_' in front.

Hope it helps. Pardon a newbie if not pertinent :-)

Claude
  • 81
  • 1
  • 2