tkinter菜单可以发送它们被调用的事件吗?

时间:2018-01-24 20:28:50

标签: python events tkinter event-handling tk

下面是我想通过发送事件数据的弹出菜单命令。我想要事件的x和y数据,所以我知道ttk样式树视图的哪个单元格(用作表格)进行操作。目前它调用" self.toggle_sort_bool"方法,但我希望它在最后调用函数" self.sort_children(event,cur_tree_children),"但不要因为我需要弄清楚在这里传递/接收事件。注意:我知道发送是自动的,但接收不是。我忽略了什么吗?

self.heading_popup_menu = tk.Menu(self.treeview, tearoff=0)
self.heading_popup_menu.add_command(label="Reverse Sort", command=self.toggle_sort_bool)

这是活动之旅的开始,右键点击ttk风格的树视图。

self.treeview.bind('<Button-3>', self.pop_up_right_click_detail)

事件的x_root和y_root被发送到tk_popup。应该/可以重载这个以发送整个事件吗?似乎根中的事件的x和y被发送以告诉弹出窗口弹出的位置。

def pop_up_right_click(self, event):
        try:
            self.heading_popup_menu.tk_popup(event.x_root, event.y_root, 0)
        finally:
            self.heading_popup_menu.grab_release()

这是我想从菜单命令调用的函数。

def sort_children(self, event, cur_tree_children):
    region = self.treeview.identify("region", event.x, event.y)

    if region == "heading":
        #get column number
        col = self.treeview.identify_column(event.x)
        col = int(re.sub('\D', '', col))

        col_names = cur_tree_children.pop(0)
        cur_tree_children.sort(reverse=self.reverse_sort_bool.get(), key=lambda tup: self.sort_disparate_types(tup[col-1])) #toggle reverse somehow
        cur_tree_children.insert(0, col_names)
        self.depopulate_tree()
        self.populate_tree()

是否可以通过菜单发送活动?我很困惑,因为缺乏更好的术语 - 事件是通过右键单击弹出菜单调用函数。虽然这是一个大的GUI类的一部分,但我不想使用类实例变量来传达目标单元格数据,因为我认为这是一个混乱和不好的做法,因此应该尽可能避免。

P.S。如果我有足够的声誉,我会制作标签BryanOakley并在其下发布。

1 个答案:

答案 0 :(得分:2)

执行所需操作的常用方法是在显示菜单之前立即修改菜单命令。您可以定义postcommand定义在显示菜单之前运行的函数,也可以在导致菜单弹出的代码中进行修改。

由于您希望将事件传递给函数,因此最佳解决方案是在弹出菜单之前修改菜单,因为该函数已经具有事件对象。

另一个选择是让你的函数设置一些实例变量,而不是修改菜单。然后,您可以在菜单中调用的函数中引用这些实例变量。

既然你说你不想使用实例变量,这里是一个显示如何修改菜单的例子:

def show_popup(self, event):
    self.popup.entryconfig("Do Something", command=lambda: self.something(event))
    self.popup.tk_popup(event.x_root, event.y_root)

实施例

这是一个完整的工作示例。代码显示一个带有树视图窗口小部件的窗口,其中包含一些虚拟数据。如果右键单击树视图,您将看到一个包含一个项目的菜单。单击该项目时,它将在标签中显示有关单击发生位置的信息。

import tkinter as tk
from tkinter import ttk

class Example(object):
    def __init__(self):
        self.root = tk.Tk()

        self.treeview = ttk.Treeview(self.root, columns=("one", "two", "three"))
        self.label = tk.Label(self.root, width=40)

        self.label.pack(side="bottom", fill="x")
        self.treeview.pack(fill="both", expand=True)

        self.popup = tk.Menu(self.root, tearoff=False)
        self.popup.add_command(label="Do something")

        self.treeview.bind('<Button-3>', self.show_popup)

        for column in self.treeview.cget("columns"):
            self.treeview.column(column, width=50)

        for i in range(10):
            values = ("a%s" % i, "b%s" %i, "c%s" %i)
            self.treeview.insert('', 'end', text="Item %s" % i, values=values)

    def start(self):
        self.root.mainloop()

    def show_popup(self, event):
        self.popup.entryconfig("Do something", command=lambda: self.do_something(event))
        self.popup.tk_popup(event.x_root, event.y_root)

    def do_something(self, event):
        region = self.treeview.identify("region", event.x, event.y)
        col = self.treeview.identify_column(event.x)

        message = "you clicked %s,%s region=%s column=%s" % (event.x, event.y, region, col)
        self.label.configure(text=message)

if __name__ == "__main__":
    Example().start()