使 tkinter 绑定使用 keycode 而不是 keysym 来实现与语言无关的绑定

问题描述 投票:0回答:1

我正在开发 Tkinter Python 程序,我需要在希腊语和其他语言之间切换进行输入。我的问题是,我必须使用重写每个键绑定并检查键代码以执行正确的功能。

widget.bind(<Control-z>, undo)

它不适用于希腊语等键盘布局。但是,如果可以指定键码而不是键符号,那就更容易了。

widget.bind(<Control-Keycode-52>, undo)

我已经制作了自己的 Entry 小部件来处理此问题,但它涉及必须编写新的复制、粘贴、选择、移动到末尾等功能。然后我必须对顶级窗口等做同样的事情...这是很多工作。

某些库中已经有这样的解决方案,或者有人有一种优雅的方法来处理这个问题吗?

python-3.x tkinter keyboard-shortcuts bind multilingual
1个回答
0
投票

我认为没有直接的方法可以

bind
Keycode
。您必须使用解决方法来完成您想要的操作。

一种方法是对

<KeyPress>
进行一般绑定,并添加一些
if-else
语句来检查特定的
Keycode

但是我考虑了通用化代码,这样就可以生成小部件可以

bind
的特殊事件,而不是仅仅使用检查。代码示例:

import tkinter as tk

root = tk.Tk()


def generate_keycode_event(event: tk.Event):
    pressed_on: tk.Widget = event.widget
    special = ''

    if isinstance(event.state, int):  # probably not needed
        state = event.state

        mods = {'Shift': 0, 'Control': 2, 'Alt': 17}
        for key in mods:
            if state & (1 << mods[key]):
                special += key + '-'

    pressed_on.event_generate(f"<<{special}Keycode-{event.keycode}>>", x=event.x, y=event.y, sendevent=event.send_event)


root.bind('<KeyPress>', generate_keycode_event)

ent = tk.Entry()
ent.pack()
ent.bind('<<Control-Keycode-90>>', lambda e: print('Undo!'))  # Keycode-90 is "z"


root.mainloop()

此代码应该允许您做您想做的事情,而无需使用

if
测试。但这可能不是理想的代码。可能会出现一些问题。

代码上的一些注释:

  1. 由于我使用的是

    root
    绑定,如果您需要将其他一些键绑定到
    root
    ,则必须在额外绑定的末尾添加
    add='+'
    参数。

  2. 如果需要,您可以添加几个额外的模组。例如,如果要定义使用的“Lock”键,可以在“mods”中添加“Lock”: 1。只需尝试使用

    event.state
    即可获得其他模组。我发现了一些:

    extra_mods = {'Shift': 0, 'Lock': 1, 'Control': 2, 'Mod1': 3, 'Mod2': 4, 'Mod3': 5, 
                  'Mod4': 6, 'Mod5': 7, 'Button1': 8, 'Button2': 9, 'Button3': 10, 
                  'Button4': 11, 'Button5': 12, 'Alt': 17, 'NumLock': 18}
    
© www.soinside.com 2019 - 2024. All rights reserved.