Tkinter 国际绑定
在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 个回答
我有一个不太完美的解决方案。在下面的代码中,我有一个窗口,里面有一个文本框,这个文本框能处理标准的 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()
我主要关心的是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时也会触发这个问题,但这又是另一个话题,因为它同样适用于英语布局。
感谢@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上测试的,使用了英语、乌克兰语、俄语、阿拉伯语、阿姆哈拉语、亚美尼亚语、希腊语、格鲁吉亚语、法语、中文、日语等多种语言布局。