Tkinter how to bind to shift+tab
Asked Answered
C

3

8

I'm trying to bind the SHIFT+TAB keys, but I can't seem to get it to work. The widget I'm binding to is an Entry widget.

I've tried binding the keys with widget.bind('<Shift_Tab>', func), but I get an error message saying:

File "/usr/lib64/python3.8/tkinter/init.py", line 1337, in _bind self.tk.call(what + (sequence, cmd)) _tkinter.TclError: bad event type or keysym "Shift_Tab"


Update

I'm still having a problem detecting SHIFT+TAB. Here is my test code. My OS is Linux. The tab key works, just not SHIFT+TAB. Seems like a simple problem to solve, so I must be going about it wrong?

I'm trying to tab between columns in a Treeview that I have overlaid widgets on a row to simulate inline editing. There can be only one active widget on a line. I keep track of what column I'm in and when the user presses SHIFT+TAB or TAB, I remove the current widget and display a new widget in the corresponding column.

Here is a link to the complete project:

The project is in one file and has no imports.

The code below is my attempt and it doesn't work.

import tkinter as tk
import tkinter.ttk as ttk


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.title('Default Demo')
        self.geometry('420x200')

        wdg = ttk.Entry(self)
        wdg.grid()

        def tab(_):
            print('Tab pressed.')

        def shift_tab(_):
            print('Shift tab pressed.')

        wdg.bind('<Tab>', tab)
        wdg.bind('<Control-ISO_Left_Tab>', shift_tab)


def main():
    app = App()
    app.mainloop()


if __name__ == '__main__':
    main()
Chicane answered 11/6, 2020 at 23:57 Comment(1)
If you want shift+tab, then the event should be <Shift-ISO_Left_Tab> instead of <Control-ISO_Left_Tab>.Lakeesha
R
5

Not a direct answer and too long for a comment.

You can solve your question by yourself with a simple trick, bind <Key> to a function, and print the key event argument passed to the bind function where you can see which key is pressed or not. Try multiple combinations of keys to see what is the state and what is their keysym or keycode.

import tkinter as tk

def key_press(evt):
    print(evt)

root = tk.Tk()
root.bind("<Key>", key_press)
root.mainloop()

It will output the following for pressing SHIFT + TAB combo on macOS.

<KeyPress event state=Shift keysym=Tab keycode=3145753 char='\x19' x=-5 y=-50>

Where,

  • state=Shift means a key event's state is on SHIFT.

  • keysym=Tab means tab key is pressed. If we just press SHIFT, the keysym will be Shift_L or Shift_R (shows Shift_L for both shift keys on mac).

  • keycode is an unique code for each key even for different key combos for example keycode for Left Shift is 131330 and keycode for TAB is 3145737 but when SHIFT + TAB is pressed the code is not the same to either, it is 3145753. (I'm not sure if these are the same code for every os but one can figure it out by printing them to the console)

  • Also, see all the event attributes.

Though bind '<Shift-Tab>' key combination works well on Mac, it can also be used like so...

def key_press(evt):
    if evt.keycode==3145753:
        print('Shift+Tab is pressed')
Roseanneroseate answered 14/6, 2020 at 11:30 Comment(0)
S
6

The following code (in python 2.7.6) should make it clear: I hope this reference works for you

from Tkinter import *

def key(event=None):
    print 'You pressed Ctrl+Shift+Tab'

root = Tk()

frame = Frame(root, width=100, height=100)
frame.focus_set()
frame.bind('<Control-Shift-KeyPress-Tab>', key)
frame.pack()

root.mainloop()

EDIT: The above works well for Windows and Mac. For Linux, use

'<Control-ISO_Left_Tab>'.
Sleepwalk answered 12/6, 2020 at 0:24 Comment(7)
for Linux use what?Chicane
I tried that on Linux and it does not work. The call back never happens.Chicane
from Tkinter import * def proof(event=None): print 'ping' root = Tk() frame = Frame(root, height=100, width=100) frame.focus_set() frame.bind('<Control-Shift-KeyPress-U>', proof) frame.pack() root.mainloop()Sleepwalk
I'm binding to an entry widget not a fame, maybe that's why?Chicane
@DanielHuckson, Please correct me if I am wrong, but this answer doesn't contain a reputable source as a citation. In your bounty description, you say you are looking for an answer from a reputable source.Monaural
i'm not reputable source? if you are not agree, it is ok, but what is your problem? be kind at leastSleepwalk
You are equally important as anyone else on this site :-). But I think the original poster of this question wants to bind Shift + Key whereas in your answer you are using Control key as well, You can edit your post and correct it.Roseanneroseate
R
5

Not a direct answer and too long for a comment.

You can solve your question by yourself with a simple trick, bind <Key> to a function, and print the key event argument passed to the bind function where you can see which key is pressed or not. Try multiple combinations of keys to see what is the state and what is their keysym or keycode.

import tkinter as tk

def key_press(evt):
    print(evt)

root = tk.Tk()
root.bind("<Key>", key_press)
root.mainloop()

It will output the following for pressing SHIFT + TAB combo on macOS.

<KeyPress event state=Shift keysym=Tab keycode=3145753 char='\x19' x=-5 y=-50>

Where,

  • state=Shift means a key event's state is on SHIFT.

  • keysym=Tab means tab key is pressed. If we just press SHIFT, the keysym will be Shift_L or Shift_R (shows Shift_L for both shift keys on mac).

  • keycode is an unique code for each key even for different key combos for example keycode for Left Shift is 131330 and keycode for TAB is 3145737 but when SHIFT + TAB is pressed the code is not the same to either, it is 3145753. (I'm not sure if these are the same code for every os but one can figure it out by printing them to the console)

  • Also, see all the event attributes.

Though bind '<Shift-Tab>' key combination works well on Mac, it can also be used like so...

def key_press(evt):
    if evt.keycode==3145753:
        print('Shift+Tab is pressed')
Roseanneroseate answered 14/6, 2020 at 11:30 Comment(0)
W
0

Here is my solution for Linux users that want to bind Shift+Tab.

def press(e):
        print('Shift+Tab is pressed')

widget.bind('<ISO_Left_Tab>',press)
Whitewood answered 17/8, 2022 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.