Tkinter 国际绑定

7 投票
5 回答
3251 浏览
提问于 2025-04-17 13:20

在Tkinter中,有没有办法绑定一组组合键,让它在所有键盘布局上都能用?(通过扫描码绑定)

举个例子,我需要一个'Control-Z'的绑定,这个绑定在所有布局中都能用,并且是键盘左下角的同一个物理按键,比如:
    * 俄文布局,
    * 希腊文布局,等等。

这是我尝试过的:

from Tkinter import *
root=Tk()
def f(event):
    print 'undo'
button1=Button(root, text=u'Button')
button1.pack()
button1.bind('<Control-z>', f)
root.mainloop()

这个方法在俄文和希腊文键盘布局上不管用。

更新-2:

我在Windows上做了一些实验,现在得出的一个大致规律是:

    1) 如果语言是基于拉丁字母的,按键是“按值”映射的(德语法语Dvorak),这样同一个动作会被映射到不同的物理按键上。
    2) 如果不是(比如俄语希腊语),那么所有主要的快捷键都是“按位置”映射的(通常与同一个按键上标记的对应英文字母匹配)。

只有第二种情况需要特别注意。有没有人知道这是否已经在某个库中实现了?

更新-3

即使没有俄文键盘或俄文Windows,这个问题也能简单复现。

1) 开始->控制面板->区域和语言选项
2) 语言->详细信息
3) 添加俄语。

就这样。现在按Alt-Shift就能切换到俄语,你就可以输入一些有趣的符号:

俄文键盘

再按一次Alt-Shift就能切换回来。

别相信维基百科说的关于俄语音标布局的内容。这些布局现在已经不常用了。至少在俄罗斯内部是这样。

所有Windows应用程序(包括wxPython的应用)都使用Ctrl-я来撤销,Ctrl-ч来剪切,Ctrl-с来复制,等等。

5 个回答

1

我有一个不太完美的解决方案。在下面的代码中,我有一个窗口,里面有一个文本框,这个文本框能处理标准的 Ctrl+C 快捷键事件。不过,如果我把键盘布局换成俄语,这些功能就不管用了。为了解决这个问题,我重新编写了这些事件的实现,现在一切都正常了。但我对这样的解决方案有点不满意。有没有人有更好的主意呢?比如,有没有办法在 Python 的 tkinter 中触发(或者模拟)“正常”的按键?

import tkinter

root = tkinter.Tk()

class MyWind (tkinter.Frame):
    def __init__(self, parent):
        tkinter.Frame.__init__(self, parent)
        self.create_UI()

    def create_UI(self):
        text_field = tkinter.Text(self)
        text_field.insert(tkinter.END, "Hello world")
        text_field.pack()

def print_event(event):
    print ("Event character code <char>: '%s'" % event.char)
    print ("   Event key symbol <keysym>: '%s'" % event.keysym)
    print ("   Event key code <keycode>: '%s'" % event.keycode)

def work_out_event(event): # Here is the solution
    widget_type = type(event.widget)
    if widget_type == tkinter.Text:
        content = event.widget.selection_get()
        print ("Selected content = '%s'" % content)
        root.clipboard_clear() 
        root.clipboard_append(content)

def lurker1(event):
    print ("Crtl + C (english) pressed!")       
    print_event(event)

def lurker2(event):
    print ("Crtl + C (russian) pressed!")
    print_event(event)
    work_out_event(event)        

root.bind("<Control-c>", lurker1)      # "C" character with the english keyboard layout
root.bind("<Control-ntilde>", lurker2) # "C" character with the russian keyboard layout

root.app = MyWind(root)
root.app.pack()
root.mainloop()
1

我主要关心的是Windows中的俄语键盘布局。

我现在使用的一个简单粗暴的解决办法是:

import Tkinter

def copy(event):
    print 'Ctrl-C'

root = Tkinter.Tk()
root.bind('<Control-ntilde>', copy)
root.mainloop()

不过,这可能会和某些其他语言中的<Ctrl + 实际的 ntilde>产生冲突。

如果我能确定当前激活的是哪个键盘布局,就可以解决这个问题。因此,第二个问题是:如何在Tkinter中确定键盘布局

另一个缺点是,由于对修饰键的“通用”处理,当我按下Ctrl-Alt-V时也会触发这个问题,但这又是另一个话题,因为它同样适用于英语布局。

2

感谢@acw1668的帮助!

要在任何语言布局中使用热键,你需要做类似下面的事情(这个例子中的回调函数会在按下控制键时运行,并同时打印出与控制键一起按下的那个键):

from tkinter import *


def callback(event):
    if (event.state & 4 > 0):
        print("Ctrl-%s pressed" % chr(event.keycode))

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

附注:这个例子是在Windows 10上测试的,使用了英语、乌克兰语、俄语、阿拉伯语、阿姆哈拉语、亚美尼亚语、希腊语、格鲁吉亚语、法语、中文、日语等多种语言布局。

撰写回答