Tkinter国际绑定

7

在Tkinter中是否有一种绑定键盘组合键的方法,可以在所有键盘布局中都起作用?(通过scancode进行绑定)

例如,我需要绑定 '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-с进行复制等等。


@AntonyHatchkins 首先你需要在Tk中解决这个问题,然后再开始关注特定的IDLE。你有一个适用于所有键盘布局的Tk解决方案吗? - mmgp
@AntonyHatchkins,你可以通过在相关的错误跟踪器上发布错误来帮助解决它,尽管很可能已经有人报告过了。即使是这种情况,你也会知道它已经被报告了,也许你可以了解为什么还没有修复。你提供的解决方法显然没有解决任何问题,因为现在它对我也不起作用。 - mmgp
真的很奇怪它没有。我已经在Windows XP、Windows Server 2003和Windows 7 Prof上进行了测试。它应该在俄语布局中按下“Ctrl-C”时打印“Ctrl-C”(不过在英语布局中需要单独绑定)。 - Antony Hatchkins
这里有一个相关讨论的维基页面 - Antony Hatchkins
1
尝试绑定<Key>事件并检查在事件处理程序中是否按下了Ctrl键(event.state&4> 0)和zevent.keycode == 90)。 - acw1668
显示剩余4条评论
5个回答

2

感谢 @acw1668 的帮助!

要在任何语言布局中使用热键,您需要像这样执行操作(此示例的回调函数在按下 Control 键时运行,并在与 Control 同时按下的键被按下时打印该键):

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上进行了检查。


1
event.keysym == "??" 可以用来检查当前键盘布局是否为英语。https://stackoverflow.com/a/65489574/1119602 - Winand
@Winand,这很棒,但与我的答案以及OP的问题无关。 - Demian Wolf
我的意思是,这可以用于热键,仅需要处理非英语布局。例如,如果您当前的布局为英语,则 Ctrl+V 粘贴文本,但对于其他布局需要手动处理。 - Winand
@Winand 问题是如何使热键在不同键盘布局下行为相同,而您正在改变它们在非英语布局下的行为。 - Demian Wolf

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时它也会触发,但对英语布局也适用。

Junuxx链接中的代码片段提供了解决后一个问题的方法:event.stateCtrl-Alt-VCtrl-V中是不同的。 - Antony Hatchkins

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()

你的回答和这个(“我目前使用的快速而肮脏的解决方法”)有什么区别? - Antony Hatchkins
没有原则性的区别,我只是想提供更多信息的代码,说明如何实际处理将操作复制到缓冲区。主要问题与您的相同:我不想重写Ctrl+C的标准功能,并且更愿意将其传递给某些内部事件处理程序。 - udavdasha

0

另一个选项已经在1999年的旧版本中建议,即从Tkinter切换到wxPython,其中加速键处理自动适用于所有类型的键盘布局(例如编辑器示例在此处:http://wiki.wxpython.org/AnotherTutorial)。


0
def copy(event):
    print 'Ctrl-C'
    master.clipboard_append('text')

它有效!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接