右键单击事件上的Tkinter Treeview标识返回上一个右键单击的行

时间:2017-07-10 09:37:23

标签: python python-3.x tkinter event-handling treeview

我在tkinter中使用python 3进行了树视图。 问题是,当我绑定右键单击以获取右键单击行的行ID时,我最终得到上一个事件的实际行ID。例如,我可能右键单击“Project 1”,这将返回“”然后我右键单击“Project 2”并返回“Project 1”作为rowID。

def initTreeView(self):
    self.treeView = ttk.Treeview(self.treeSectionFrame)
    self.treeView.heading('#0', text='Projects')

    self.treeView.grid(row=0, column=0, sticky=("N", "S", "E", "W"))            


    self.treeView.bind('<3>', self.rightClickMenu)

def rightClickMenu(self, event):
    def hello():
        print("hello!")
    # create a popup menu
    print(event.x, event.y)
    rowID = self.treeView.identify('item', event.x, event.y)
    if rowID:
        menu = Menu(self.root, tearoff=0)
        menu.add_command(label="Undo", command=hello)
        menu.add_command(label="Redo", command=hello)
        menu.post(event.x_root, event.y_root)

        self.treeView.selection_set(rowID)
        self.treeView.focus_set()
        self.treeView.focus(rowID)
        print(rowID)
    else:
        pass

谢谢,

[编辑]

我发现了一个肮脏的黑客,其中包括使每个项目的标签与其id相同,以便您可以获取实际的rowID。这也可以使用值选项完成。

self.treeView.insert("", "end", "id-1, tags="id-1", text="Project 1")

...
rowID = self.treeView.identify('item', event.x, event.y)
rowID = self.treeView.item(rowID)["tags"] # gives you actual ID

1 个答案:

答案 0 :(得分:1)

首先,如果您想打印实际的rowID,请立即打印出来:

...
rowID = self.treeView.identify('item', event.x, event.y)
print(rowID)
...

...但当然,这不是您对代码的期望。要克服这个问题 - 让我们稍微颠倒逻辑:

def rightClickMenu(self, event):
    def hello():
        print("hello!")
    # create a popup menu
    print(event.x, event.y)
    rowID = self.treeView.identify('item', event.x, event.y)
    if rowID:
        self.treeView.selection_set(rowID)
        self.treeView.focus_set()
        self.treeView.focus(rowID)
        print(rowID)

        menu = Menu(self.root, tearoff=0)
        menu.add_command(label="Undo", command=hello)
        menu.add_command(label="Redo", command=hello)
        menu.post(event.x_root, event.y_root)
    else:
        pass

如您所见,现在更改选择不会被Menu小部件阻止。

之所以这样,是因为post方法会立即显示Menu,而且此事件需要以某种方式由tk处理。因此,我们有一个主要问题:post的定位。

另一个方法示例:

    ...
    menu = Menu(self.root, tearoff=0)
    menu.add_command(label="Undo", command=hello)
    menu.add_command(label="Redo", command=hello)

    self.treeView.selection_set(rowID)
    self.treeView.focus_set()
    self.treeView.focus(rowID)
    print(rowID)
    menu.post(event.x_root, event.y_root)
    ...

但在我看来,我认为这里最正确的选择是将选择处理提取到另一个函数,并将其用作postcommand的{​​{1}}参数。因此,在此之后,您不会尝试使用一个回调函数同时坐在两把椅子上。