I previously found that there are some limitations with native menus that I'm not happy with (that is, they steal many events and won't share).
Bryan Oakly suggested that I write my own menu class, which can share the events that a native menu steals. I figured I'd do it by putting a Listbox
on a featureless Toplevel
. One of the behaviors that you'd expect from a Menu
that isn't built into the Listbox
is having it highlight items as you mouse over them.
Here's the code I wrote to accomplish this:
import Tkinter as tk
class Menu(tk.Listbox):
def __init__(self, master, items, *args, **kwargs):
tk.Listbox.__init__(self, master, exportselection = False, *args, **kwargs)
self.pack()
for item in items:
self.insert(tk.END, item)
self.bind('<Enter>', lambda event: self.snapHighlightToMouse(event))
self.bind('<Motion>', lambda event: self.snapHighlightToMouse(event))
self.bind('<Leave>', lambda _: self.unhighlight())
def snapHighlightToMouse(self, event):
self.selection_clear(0, tk.END)
self.selection_set(self.nearest(event.y))
def unhighlight(self):
self.selection_clear(0, tk.END)
m = Menu(None, ['Alice', 'Bob', 'Caroline'])
tk.mainloop()
This kind of works. Sometimes the highlight follows the cursor. Sometimes it seems to get stuck for no particular reason. It's not consistent, but I find the most reliable way to get it stuck is to enter from the left or right side onto Caroline, then move up to Bob and/or Alice - Caroline will remain the highlighted item.
Similarly, entering from the top often doesn't trigger an Enter event - Alice doesn't get highlighted (nor do the others as I mouse over them).
Is there something I'm doing wrong? Is there something I can do to make the highlight more reliably follow the mouse cursor?
Leave seem to always trigger without fail - it's just Motion and Enter that are hit or miss.