python - Tkinter Treeview 右键单击​​事件识别返回上一个右键单击行

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

我在 tkinter 中有一个使用 python 3 的 TreeView 。 问题是,当我绑定(bind)右键单击以获取右键单击行的行 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。这也可以使用 value 选项来完成。

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

最佳答案

首先,如果你想打印实际的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 以某种方式处理。因此,我们遇到了主要问题:该帖子的定位。

另一种方法示例:

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

但在我看来,我认为这里逻辑上最正确的选项是将选择处理提取到另一个函数,并将其用作 Menupostcommand 参数。这样一来,您就不会尝试使用一个回调函数同时坐在两把椅子上。

关于python - Tkinter Treeview 右键单击​​事件识别返回上一个右键单击行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45008580/

相关文章:

python - matplotlib plt.show() 预索引空 numpy 数组时出现视觉故障

python - 使用迭代器作为列和索引更快地将总和值附加到数据帧

python - 为什么node.js读取文件比python快?

python - 如何用键盘激活 tkinter 按钮?

python - 如果将每个 View 类移动到单独的 .py 文件,是否会影响性能?

python - Django:先有鸡还是先有蛋的问题

python - 尝试使用 Python 3.7.2 和 IMAPClient 批量删除电子邮件 - imaplib.IMAP4.error : UID command error: BAD [b'Command line too large']

python - 用自定义消息替换错误

python - tkinter (python) 中的 IPAD-X/Y 和 PAD-X/Y 是否不同?

python - flask 单元测试 : how to test request from logged in user