Recipe 11.5. Entering Accented Characters in Tkinter WidgetsCredit: Artur de Sousa Rocha ProblemYou want your application to allow the user to easily enter accented characters into Tkinter widgets even from a U.S.-layout keyboard. SolutionInternationalized applications should enable the user to easily enter letters with accents and diacritics (e.g., umlauts, and tildes) even from a U.S.-layout keyboard. A usefully uniform convention is the following: hitting Ctrl-accent, for any kind of accent or diacritic, acts as a dead key, ensuring that the next letter hit will be decorated by that accent or diacritic. For example, Ctrl-apostrophe, followed by a, enters an a with an acute accent (the character á). The following classes provide the keyboard and widget bindings that allow this internationalized input functionality: from Tkinter import * from ScrolledText import ScrolledText from unicodedata import lookup import os class Diacritical(object): """ Mixin class that adds keyboard bindings for accented characters, plus other common functionality (e.g.: Control-A == 'select all' on Windows). """ if os.name == "nt": stroke = '/' else: stroke = 'minus' accents = (('acute', "'"), ('grave', '`'), ('circumflex', '^'), ('tilde', '='), ('diaeresis', '"'), ('cedilla', ','), ('stroke', stroke)) def _ _init_ _(self): # Fix some non-Windows-like Tk bindings, if we're on Windows if os.name == 'nt': self.bind("<Control-Key-a>", self.select_all) self.bind("<Control-Key-/>", lambda event: "break") # Diacritical bindings for a, k in self.accents: self.bind("<Control-Key-%s><Key>" % k, lambda event, a=a: self.insert_accented(event.char, a)) def insert_accented(self, c, accent): if c.isalpha( ): if c.isupper( ): cap = 'capital' else: cap = 'small' try: c = lookup("latin %s letter %c with %s" % (cap, c, accent)) self.insert(INSERT, c) return "break" except KeyError, e: pass class DiacriticalEntry(Entry, Diacritical): """ Tkinter Entry widget with some extra key bindings for entering typical Unicode characters - with umlauts, accents, etc. """ def _ _init_ _(self, master=None, **kwargs): Entry._ _init_ _(self, master=None, **kwargs) Diacritical._ _init_ _(self) def select_all(self, event=None): self.selection_range(0, END) return "break" class DiacriticalText(ScrolledText, Diacritical): """ Tkinter ScrolledText widget with some extra key bindings for entering typical Unicode characters - with umlauts, accents, etc. """ def _ _init_ _(self, master=None, **kwargs): ScrolledText._ _init_ _(self, master=None, **kwargs) Diacritical._ _init_ _(self) def select_all(self, event=None): self.tag_add(SEL, "1.0", "end-1c") self.mark_set(INSERT, "1.0") self.see(INSERT) return "break" DiscussionHere is an example of use of these widget classes. We present the example, as usual, with a guard of if _ _name_ _ == '_ _main_ _'; so we can make it part of the module containing the classes and have it run when the module is executed as a "main script": def test( ): frame = Frame( ) frame.pack(fill=BOTH, expand=YES) if os.name == "nt": frame.option_add("*font", "Tahoma 8") # Win default, Tk uses other # The editors entry = DiacriticalEntry(frame) entry.pack(fill=BOTH, expand=YES) text = DiacriticalText(frame, width=76, height=25, wrap=WORD) if os.name == "nt": text.config(font="Arial 10") text.pack(fill=BOTH, expand=YES) text.focus( ) frame.master.title("Diacritical Editor") frame.mainloop( ) if _ _name_ _ == "_ _main_ _": test( ) You might want to remove the keyboard event settings that don't really have much to do with accents and diacritics, (e.g., Ctrl-A, meaning "select all") to some other, separate mixin class. I keep that functionality together with the actual handling of diacritics basically because I always need both features anyway. Some design choices might be altered, such as my decision to have Ctrl-equal as the way to enter a tilde. I took that path because I just couldn't find a way to make Ctrl-~ work the right way, at least on my Windows machine! Also, depending on which languages you need to support, you might have to add other accents and diacritics, such as a-ring for Swedish, German scharfes-s, Icelandic eth and thorn, and so forth. See AlsoDocs about the unicodedata module in the Library Reference and Python in a Nutshell; information about Tkinter can be obtained from a variety of sources, such as Pythonware's An Introduction to Tkinter, by Fredrik Lundh (http://www.pythonware.com/library), New Mexico Tech's Tkinter Reference (http://www.nmt.edu/tcc/help/lang/python/docs.html), Python in a Nutshell, and various other books. |