【问题标题】:Tkinter TreeView binding left click to the current tree and selected itemTkinter TreeView 绑定左键点击当前树和选中项
【发布时间】:2018-04-23 06:58:11
【问题描述】:

我正在尝试将此函数 self.copyTextToClipboard(self,t) 绑定到多个不同的树以使其更灵活(请参阅下面的绑定)。 从 tkinter.ttk 导入 Treeview 从 tkinter 导入 *

class App:
    def __init__(self, master):
        self.master = master
        frame = Frame(master)

        master.geometry("{}x{}".format(master.winfo_screenwidth() - 100, master.winfo_screenheight() - 100))
        master.resizable(False, False)

        self.leftFrame = Frame(master, bg="#DADADA", width=375, relief=SUNKEN)
        self.leftFrame.pack_propagate(0)
        self.leftFrame.pack(side=LEFT, fill=Y, padx=1)

        # This table (TreeView) will display the partitions in the tab
        self.partitionsOpenDiskTree = Treeview(self.leftFrame, columns=("#"), show="headings", selectmode="browse", height=23)

        yscrollB = Scrollbar(self.leftFrame)
        yscrollB.pack(side=RIGHT, fill=Y)

        self.partitionsOpenDiskTree.column("#", width=50)
        self.partitionsOpenDiskTree.heading("#", text="#")
        self.partitionsOpenDiskTree.configure(yscrollcommand=yscrollB.set)

        # Bind left click on text widget to copy_text_to_clipboard() function
        self.partitionsOpenDiskTree.bind("<ButtonRelease-1>", lambda t=self.partitionsOpenDiskTree: self.copyTextToClipboard(self,t))

        # Adding the entries to the TreeView
        for i in range(3):
            self.partitionsOpenDiskTree.insert("", "end", i, values=(i), tags=str(i))

        self.partitionsOpenDiskTree.pack(anchor=NW, fill=Y)

    #todo: figure out where this is getting called and put in tree
    def copyTextToClipboard(self, tree, event=None):
        print(type(tree))
        # triggered off left button click on text_field
        root.clipboard_clear()  # clear clipboard contents
        textList = tree.item(tree.focus())["values"]
        line = ""
        for text in textList:
            if line != "":
                line += ", " + str(text)
            else:
                line += str(text)

        root.clipboard_append(line)  # append new value to clipbaord

root = Tk()
app = App(root)
root.mainloop()

但是,我似乎无法将它绑定到 TreeView 对象;当我运行代码时,我得到:

Exception in Tkinter callback
<class '__main__.App'>
Traceback (most recent call last):
  File "C:\Users\user1\Anaconda3\lib\tkinter\__init__.py", line 1699, in __call__
    return self.func(*args)
  File "C:/Users/user1/main_merged.py", line 56, in <lambda>
    lambda t=self.partitionsOpenDiskTree: self.copyTextToClipboard(self,t))
  File "C:/Users/user1/main_merged.py", line 70, in copyTextToClipboard
    textList = tree.item(tree.focus())["values"]
AttributeError: 'App' object has no attribute 'item'

如果我尝试打印树类型,我会发现它不是 TreeView 对象。关于如何获取 TreeView 对象的任何想法,以便我可以确定选择了哪个项目?

谢谢! -FF

【问题讨论】:

  • 请修正您的缩进,以便我们检查“您的”代码
  • 似乎有很多额外的代码。请尝试将其减少到minimal reproducible example。如果您的问题与 Treeview 绑定有关,您只需要几个小部件、绑定语句和绑定函数。
  • 我更新了代码以反映上述 cmets。
  • 看来tree 不是你想的那样。你做了什么来调试这个?您在致电tree.item 之前检查过数据吗?
  • t 作为之前的输入是一棵树,当它被赋予绑定函数时,它变成了一个 App 类型,这对我来说似乎很奇怪。我不确定为什么它会在绑定中转换为不同的类型。有什么想法吗?

标签: python tkinter treeview


【解决方案1】:

因此,显然,取出 self 调用似乎有效:

from tkinter.ttk import Treeview
from tkinter import *

class App:
    def __init__(self, master):
        self.master = master
        frame = Frame(master)

        master.geometry("{}x{}".format(master.winfo_screenwidth() - 100, master.winfo_screenheight() - 100))
        master.resizable(False, False)

        self.leftFrame = Frame(master, bg="#DADADA", width=375, relief=SUNKEN)
        self.leftFrame.pack_propagate(0)
        self.leftFrame.pack(side=LEFT, fill=Y, padx=1)

        # This table (TreeView) will display the partitions in the tab
        self.partitionsOpenDiskTree = Treeview(self.leftFrame, columns=("#"), show="headings", selectmode="browse", height=23)

        yscrollB = Scrollbar(self.leftFrame)
        yscrollB.pack(side=RIGHT, fill=Y)

        self.partitionsOpenDiskTree.column("#", width=50)
        self.partitionsOpenDiskTree.heading("#", text="#")
        self.partitionsOpenDiskTree.configure(yscrollcommand=yscrollB.set)

        # Bind left click on text widget to copy_text_to_clipboard() function
        self.partitionsOpenDiskTree.bind("<ButtonRelease-1>", lambda event, t=self.partitionsOpenDiskTree: self.copyTextToClipboard(t))

        # Adding the entries to the TreeView
        for i in range(3):
            self.partitionsOpenDiskTree.insert("", "end", i, values=(i), tags=str(i))

        self.partitionsOpenDiskTree.pack(anchor=NW, fill=Y)

    #todo: figure out where this is getting called and put in tree
    def copyTextToClipboard(self, tree, event=None):
        print(type(tree))
        # print(type(tree.partitionsOpenDiskTree))
        # triggered off left button click on text_field
        root.clipboard_clear()  # clear clipboard contents
        textList = tree.item(tree.focus())["values"]
        line = ""
        for text in textList:
            if line != "":
                line += ", " + str(text)
            else:
                line += str(text)

        root.clipboard_append(line)  # append new value to clipbaord
        print(line)

root = Tk()
app = App(root)
root.mainloop()

输出: 0

【讨论】:

    【解决方案2】:

    当你使用bind时,回调函数必须有一个event作为它的第一个参数,自定义参数应该放在后面。但由于您的回调不需要事件参数,您可以用您的 lambda 屏蔽它。因此,您必须同时更改绑定和回调的def

    self.partitionsOpenDiskTree.bind("<ButtonRelease-1>", lambda event, t=self.partitionsOpenDiskTree: self.copyTextToClipboard(t))
    
    ...
    
    def copyTextToClipboard(self, tree):
    

    应该解决问题

    【讨论】:

    • 我尝试了上面的方法,这给了我以下错误: Tkinter 回调 Traceback 中的异常(最近一次调用最后一次):文件“C:\Users\user1\Anaconda3\lib\tkinter_init_ .py”,第 1699 行,在 call 中返回 self.func(*args) 文件“C:/Users/user1/main_merged.py”,第 28 行,在 self .partitionsOpenDiskTree.bind("", lambda event, t=self.partitionsOpenDiskTree: self.copyTextToClipboard(self,t)) TypeError: copyTextToClipboard() 需要 2 个位置参数,但给出了 3 个 ------ (不确定如何格式化以使其出现在多行上。)
    • 糟糕,我忘了在你的 lambda 中取消 self 参数(由 Python 自动提供)。我已经编辑了答案,但我看到你已经自己找到了更正。
    • self 参数解释了为什么解释器告诉你tree 的类型是App,因为当你手动添加self 时它变成了第二个参数,所以它是链接的到tree
    • 啊是的。这是有道理的。
    猜你喜欢
    • 1970-01-01
    • 2012-08-16
    • 2020-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    相关资源
    最近更新 更多