Tkinter - 光标后面的列表框?

时间:2016-01-18 04:27:54

标签: python macos menu tkinter listbox

I previously found本机菜单存在一些限制,我不满意(也就是说,它们窃取了很多事件而且不会共享)。

Bryan Oakly suggested我编写自己的菜单类,可以共享本机菜单窃取的事件。我想通过在无特征的Listbox上加Toplevel来做到这一点。 Menu中没有内置于Listbox的{​​{1}}期望的行为之一就是让鼠标悬停在项目上时突出显示项目。

以下是我为实现此目的而编写的代码:

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

这种作品。有时突出显示在光标后面。有时似乎没有特别的原因卡住了。它并不一致,但我发现让它卡住的最可靠的方法是从左侧或右侧进入Caroline,然后向上移动到Bob和/或Alice - Caroline仍将是突出显示的项目。

同样,从顶部进入通常不会触发Enter事件 - Alice不会突出显示(其他人也不会突出显示)。

我有什么问题吗?有什么我可以做的事情可以更加可靠地跟随鼠标光标吗?

保持似乎始终触发而不失败 - 只是动作和输入被击中或错过。

1 个答案:

答案 0 :(得分:0)

值得注意的是,绑定事件时会将事件传递给被调用的函数,因此您可以更改代码以删除lambdas,如下所示:

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>',  self.snapHighlightToMouse)
        self.bind('<Motion>', self.snapHighlightToMouse)
        self.bind('<Leave>',  self.unhighlight)

    def snapHighlightToMouse(self, event):
        self.selection_clear(0, tk.END)
        self.selection_set(self.nearest(event.y))

    def unhighlight(self, event=None):
        self.selection_clear(0, tk.END)

m = Menu(None, ['Alice', 'Bob', 'Caroline'])

tk.mainloop()

我知道严格来说,这并不能解决您的问题,但可能会使您的代码过于复杂/瘫痪,并且不会轻易放入评论中。我无法访问Mac,但值得一试。