Chmod
Chmod

Reputation: 107

Tkinter TreeView binding left click to the current tree and selected item

I am trying to bind this function self.copyTextToClipboard(self,t) to multiple different trees to make it more flexible (please see binding below). 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 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()

However, I am unable to bind it to a TreeView object it seems; when I run the code, I get:

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'

If I try to print out tree type, I get that it's a not a TreeView object. Any ideas on how I can get a TreeView object, so that I can figure out which item was selected?

Thanks! -FF

Upvotes: 1

Views: 4443

Answers (2)

sciroccorics
sciroccorics

Reputation: 2427

When you use bind, the callback function must have an event as its first argument, custom arguments should be put after. But as your callback does not need the event parameters, you may mask it with your lambda. So you have to change both the binding and the def of your callback:

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

...

def copyTextToClipboard(self, tree):

should solve the problem

Upvotes: 1

Chmod
Chmod

Reputation: 107

So, apparently, taking out the self call seemed to work:

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

Output: 0

Upvotes: 1

Related Questions