Multiple Key Event Bindings in Tkinter - “Control + E” “Command (apple) + E” etc

点点圈 提交于 2019-12-01 16:48:01

This appears to be a bug in Tk. I get the same error with tcl/tk on the mac as well as with python/tkinter. You can bind <Command-e> to a widget (I tried with a text widget) but binding it to the root window or to "all" seems to cause the error you get.

With Tkinter, "Control-R" means Ctrl-Shift-R whereas "Control-r" means Ctrl-R. So make sure you're not mixing up uppercase and lowercase.

Something like this:

# Status of control, shift and control+shift keys in Python
import tkinter as tk

ctrl = False
shift = False
ctrl_shift = False

def key(event):
    global ctrl, shift, ctrl_shift
    #print(event.keycode, event.keysym, event.state)
    if ctrl_shift:
        print('<Ctrl>+<Shift>+{}'.format(event.keysym))
    elif ctrl:
        print('<Ctrl>+{}'.format(event.keysym))
    elif shift:
        print('<Shift>+{}'.format(event.keysym))
    ctrl = False
    shift = False
    ctrl_shift = False

def control_key(state, event=None):
    ''' Controll button is pressed or released '''
    global ctrl
    ctrl = state

def shift_key(state, event=None):
    ''' Controll button is pressed or released '''
    global shift
    shift = state
    control_shift(state)

def control_shift(state):
    ''' <Ctrl>+<Shift> buttons are pressed or released '''
    global ctrl, ctrl_shift
    if ctrl == True and state == True:
        ctrl_shift = True
    else:
        ctrl_shift = False

root = tk.Tk()
root.geometry('256x256+0+0')

root.event_add('<<ControlOn>>',  '<KeyPress-Control_L>',   '<KeyPress-Control_R>')
root.event_add('<<ControlOff>>', '<KeyRelease-Control_L>', '<KeyRelease-Control_R>')
root.event_add('<<ShiftOn>>',    '<KeyPress-Shift_L>',     '<KeyPress-Shift_R>')
root.event_add('<<ShiftOff>>',   '<KeyRelease-Shift_L>',   '<KeyRelease-Shift_R>')

root.bind('<<ControlOn>>', lambda e: control_key(True))
root.bind('<<ControlOff>>', lambda e: control_key(False))
root.bind('<<ShiftOn>>', lambda e: shift_key(True))
root.bind('<<ShiftOff>>', lambda e: shift_key(False))
root.bind('<Key>', key)

root.mainloop()

Enhanced to cover the Alt and Meta keys, aka Option and Command on macOS.

# Original <https://StackOverflow.com/questions/6378556/
#           multiple-key-event-bindings-in-tkinter-control-e-command-apple-e-etc>

# Status of alt (ak option), control, meta (aka command)
# and shift keys in Python tkinter

# Note, tested only on macOS 10.13.6 with Python 3.7.4 and Tk 8.6.9

import tkinter as tk
import sys

_macOS = sys.platform == 'darwin'
_Alt   = 'Option' if _macOS else 'Alt'
_Ctrl  = 'Control'
_Meta  = 'Command' if _macOS else 'Meta'
_Shift = 'Shift'

alt = ctrl = meta = shift = ''


def up_down(mod, down):
    print('<%s> %s' % (mod, 'down' if down else 'up'))
    return down


def key(event):
    '''Other key pressed or released'''
    # print(event.keycode, event.keysym, event.down)
    global alt, ctrl, meta, shift
    t = [m for m in (alt, ctrl, shift, meta, str(event.keysym)) if m]
    print('+'.join(t))


def alt_key(down, *unused):
    '''Alt (aka Option on macOS) key is pressed or released'''
    global alt
    alt = up_down(_Alt, down)


def control_key(down, *unused):
    '''Control key is pressed or released'''
    global ctrl
    ctrl = up_down(_Ctrl, down)


def meta_key(down, *unused):
    '''Meta (aka Command on macOS) key is pressed or released'''
    global meta
    meta = up_down(_Meta, down)


def shift_key(down, *unused):
    '''Shift button is pressed or released'''
    global shift
    shift = up_down(_Shift, down)


def modifier(root, mod, handler, down):
    '''Add events and handlers for key press and release'''
    root.event_add('<<%sOn>>' % (mod,), ' <KeyPress-%s_L>' % (mod,), '<KeyPress-%s_R>' % (mod,))
    root.bind(     '<<%sOn>>' % (mod,), lambda _: handler('<%s>' % (down,)))

    root.event_add('<<%sOff>>' % (mod,), '<KeyRelease-%s_L>' % (mod,), '<KeyRelease-%s_R>' % (mod,))
    root.bind(     '<<%sOff>>' % (mod,), lambda _: handler(''))


root = tk.Tk()
root.geometry('256x64+0+0')

modifier(root, 'Alt',     alt_key,     _Alt)
modifier(root, 'Control', control_key, _Ctrl)
modifier(root, 'Meta',    meta_key,    _Meta)
modifier(root, 'Shift',   shift_key,   _Shift)

root.bind('<Key>', key)

root.mainloop()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!