Tkinter international bind

我的梦境 提交于 2019-12-02 02:04:26

问题


Is there a way in Tkinter to bind a combination of keys that will work in all keyboard layouts? (bind by scancode)

For example, I need 'Control-Z' binding that will work with the same physical key in the lower left corner of the keyboard in all layouts, such as:
    * Russian layout,
    * Greek layout, etc.

Here's what I tried:

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

It doesn't work for Russian and Greek keyboard layouts.

Update-2:

I did some more experiments with Windows and now the general rule is like that:

    1) If the language is based on latin character set, keys are mapped "by value" (German, French, Dvorak) so that the same action is mapped to different physical keys.
    2) If it is not (eg Russian, Greek), then all major accelerators are mapped "by position" (to match the corresponding English letter usually marked on the same key).

Only the second case needs special attention. Any ideas if this is implemented in some lib already?

Update-3

It is simply reproduced even without Russian keyboard or Russian Windows.

1) Start->Control Panel->Regional and Language Options
2) Language->Details
3) Add Russian language.

That's it. Now Alt-Shift will switch you to Russian and you'll be able to type the following funny symbols:

another Alt-Shift will switch you back.

Forget what Wikipedia says about phonetic Russian layouts. They are not used these days. At least inside Russia.

All Windows applications (including wxPython ones) use Ctrl-я for undo, Ctrl-ч for cut, Ctrl-с for copy and so on.


回答1:


What I'm primarily interested in is Russian layout in Windows.

The quick and dirty workaround I currently use is:

import Tkinter

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

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

which could potentially lead to a conflict with <Ctrl + actual ntilde> in some other language.

It could be overcome if I could determine which layout is currently active, thus second question: Tkinter determine keyboard layout.

Another drawback is that due to 'universal' treatment of modifier keys it also fires when I press Ctrl-Alt-V, but that's another story as it applies to English layout as well.




回答2:


Another option already suggested in the old 1999 is to switch from Tkinter to wxPython where accelerators handling is done for all types of keyboard layouts automatically (eg Editor example here: http://wiki.wxpython.org/AnotherTutorial).




回答3:


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

and it works!




回答4:


I have a partial and rather ugly solution for this. In the code below I have a window with Text widget, which have some "in-box" connection between standard Ctrl+C keyboard events and their proper handling. However, if I simply change the keyboard layout to, say, Russian, these functions do not work anymore. To solve the problem I re-wrote implementation for these events, and now everything works fine. But I feel slightly frustrated about such a solution. Does anyone have any better ideas?.. For instance, is there a way to trigger (or mimic) "normal" key press in 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()


来源:https://stackoverflow.com/questions/14455625/tkinter-international-bind

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