Question: How to Prevent Tkinter Menu from Taking Keyboard Focus

galyle galyle at gmail.com
Tue Oct 4 13:05:49 EDT 2011


On Oct 4, 9:45 am, woooee <woo... at gmail.com> wrote:
> Sorry, I did not understand the question correctly, and so have added
> another focus_set for the entry after the menu's creation.  You can
> still enter after the menu comes up, even though you can't see where
> you are entering.
>
> import Tkinter
>
> class demo:
>     def __init__(self, parent):
>         self._entry = Tkinter.Entry(width = 60)
>         self._suggestions = Tkinter.Menu(parent, tearoff = 0,
> takefocus = 0)
>         self._entry.pack(padx = 20, pady = 20)
>         self._entry.bind('<Key>', self._suggest_text, add = '+')
>         self._entry.focus_set()
>
>     def _suggest_text(self, event):
>         curr = self._entry.get() + repr(event.char)[1]
>         x = self._entry.winfo_rootx()
>         y = self._entry.winfo_rooty()
>         y += self._entry.winfo_height()
>         try:
>             self._suggestions.delete(0, 'end')
>             self._suggestions.add_command(label = curr + '_1')
>             self._suggestions.add_command(label = curr + '_2')
>             self._suggestions.add_command(label = curr + '_3')
>             self._suggestions.add_command(label = curr + '_4')
>             self._suggestions.post(x, y)
>         finally:
>             self._suggestions.grab_release()
>
>         self._entry.focus_set()
>
> if __name__ == '__main__':
>     root = Tkinter.Tk()
>     root.title('A Problem')
>     demo(root)
>     root.mainloop()

Perhaps it is because I'm trying this on Windows, but the above code
does not work for me.  After the menu is posted, no further keyboard
input gets directed to the entry until the menu is unposted.

It looks like my best bet is to use the ComboBox suggested above.  The
ComboBox method is very close to working, but I've got a problem now
where all focus on the app is directed to the ComboBox entry (I need
to set it that way to redirect keyboard input from the popup menu),
making it impossible to close the app without killing it.  I've tried
to return focus to the entry parent by binding the entry to <FocusOut>
and <Leave>, but this has the effect of making the popup take the
focus after every keystroke, which is not what I want.

The (almost working) demo below should demonstrate the issue fairly
well:

import Tkinter
import Pmw

class demo:
    def __init__(self, parent):
        self._search_bar = Pmw.ComboBox(parent,
            label_text = 'Register Mnemonic',
            labelpos = 'w', entry_width = 60)
        self._search_bar.pack(padx = 20, pady = 20)
        self._search_bar._entryfield.component('entry').bind('<Key>',
            self._suggest_text, add = '+')

    def _suggest_text(self, event):
        curr = self._search_bar._entryfield.getvalue()
        curr += repr(event.char)[1]
        self._search_bar._list.setlist([curr + '_0', curr + '_1',
            curr + '_2'])
        self._search_bar._postList(event)
        self._search_bar._entryfield.component('entry').focus_set()
        self._search_bar._popup.lift()

if __name__ == '__main__':
    root = Tkinter.Tk()
    root.title('A Problem')
    demo(root)
    root.mainloop()



More information about the Python-list mailing list