Skip to content Skip to sidebar Skip to footer

Tkinter International Bind

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 s

Solution 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.

Solution 2:

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

classMyWind (tkinter.Frame):
    def__init__(self, parent):
        tkinter.Frame.__init__(self, parent)
        self.create_UI()

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

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

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

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

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

Solution 3:

Thanks to @acw1668 for help!

You need to do something like this to use hotkeys with any language layout (the callback from this example is running when Control key is pressed, and prints the key that is pressed in the same time with 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()

PS: This example was checked on Windows 10 when English, Ukrainian, Russian, Arabic, Amharic, Armenian, Greek, Georgian, French, Chinese, Japanese and other language layouts were used.

Solution 4:

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

Solution 5:

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

and it works!

Post a Comment for "Tkinter International Bind"