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

Python Tkinter Treeview右键单击时标识事件返回上一个右键单击行,python,python-3.x,tkinter,event-handling,treeview,Python,Python 3.x,Tkinter,Event Handling,Treeview,我在tkinter中有一个使用Python3的树视图。 问题是,当我绑定右键单击以获取右键单击行的行ID时,我最终会获取上一个事件的实际行ID。例如,我可能右键单击“项目1”,这将返回我“”,然后我右键单击“项目2”,它将返回“项目1”作为rowID def initTreeView(self): self.treeView = ttk.Treeview(self.treeSectionFrame) self.treeView.heading('#0', text='Projec

我在tkinter中有一个使用Python3的树视图。 问题是,当我绑定右键单击以获取右键单击行的行ID时,我最终会获取上一个事件的实际行ID。例如,我可能右键单击“项目1”,这将返回我“”,然后我右键单击“项目2”,它将返回“项目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

首先,如果要打印实际的
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
如您所见,现在更改选择不会被
菜单
小部件阻止

它这样工作的原因是该方法立即显示
菜单
,并且该事件需要由
tk
以某种方式处理。因此,我们有一个主要问题:那篇文章的定位

另一个方法示例:

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

但在我看来,我认为逻辑上最正确的选择是将选择处理提取到另一个函数,并将其用作
菜单
后命令
参数。这样一来,您就不会试图同时坐在两张椅子上,只使用一个回调函数。

谢谢,现在可以很好地工作了。反转它是如何工作的?@我是Legend,因为事件队列中存在某种重叠(我假设),它看起来像
tkinter
返回mainloop,因为用户可以与菜单交互,并且在菜单可见时阻止代码执行。无论如何,我稍微更新了我的答案。
    ...
    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)
    ...