1

My Python program has two classes that are basically modified versions of Tkinter's Treeview Widget. The reason for the two different classes is that they have different methods for when items within them are double-clicked, selected etc.

The program creates an instance of each class, named tree_dialog_tv1 and tree_dialog_tv2 respectively.

I have a method in the class for the tree_dialog_tv1 bound to double-click that highlights the current row, or un-highlights if, if already highlighted. The instance of the second class, tree_dialog_tv2, is meant to list a copy of only the rows in tree_dialog_tv1 that are currently selected, adding new selections added in tree_dialog_tv1 and removing any unselected in tree_dialog_tv1.

What I don't know is where to put the code for adding/removing items in tree_dialog_tv2 based on the items double-clicked in tree_dialog_tv1. Should this code be added to the existing double-click-bound method in the class for tree_dialog_tv1, and if so, how should I reference the tree_dialog_tv2 instance (which belongs to a completely difference class) so that its contents can be updated?

class MyTreeview1(ttk.Treeview):
    def __init__(self, master, **kw):
        super().__init__(master, **kw)

        self.bind("<<TreeviewSelect>>", self.on_tree_item_select)

    def on_tree_item_select(self, event):
        #code for highlighting/unhighlighting rows here

class MyTreeview2(ttk.Treeview):
    def __init__(self, master, **kw):
        super().__init__(master, **kw)

        self.bind("<Double-1>", self.on_double_click)

    def on_double_click(self, event):
        #various lines of code (omitted for simplicity)


if __name__ == "__main__":

    tree_dialog_tv1 = MyTreeview1(root)
    tree_dialog_tv2 = MyTreeview2(root)
    
    tree_dialog_tv1.grid(row=0,column0)
    tree_dialog_tv2.grid(row=0,column1)
    
    root.mainloop()

Ultimately actions in instance of one Treeview class need to affect contents of instance of completely different Treeview class, but not sure how to call.

2
  • You need to pass the instance of one class to the instance of another class. Commented Oct 31, 2022 at 15:03
  • Thanks for the reply. Just not sure exactly how to do that. I need the instance of the second class (tree_dialog_tv2) to update in response to the user selecting a row in the instance of the first treeview class (tree_dialog_tv1). The select event on the first instance (<<TreeviewSelect>>) is bound to the method "on_tree_item_select" which obtains the contents of the selected row and stores in a list variable (although not shown in above code). Part of the challenge is needing to pass the list variable to tree_dialog_tv2 each time a row is selected in the instance of the first class. Commented Oct 31, 2022 at 16:26

1 Answer 1

1

What I like to do in such cases is to use a common master, mostly a tk.Frame. It is a convenient way to connect two or more widgets which each other, since tkinter already stores the master for each widget, which can be addressed in a class with self.master. This way you can easily address every widget in the parent, e.g self.master.tree_dialog_tv1 and create a message system for two or more widgets.

import tkinter as tk
from tkinter import ttk

class MyTreeview1(ttk.Treeview):
    def __init__(self, master, **kw):
        super().__init__(master, **kw)

    def message_input(self, msg):
        print(msg)
        return

class MyTreeview2(ttk.Treeview):
    def __init__(self, master, **kw):
        super().__init__(master, **kw)
        self.bind("<Double-1>", lambda e:self.notify_tv1('hello from 2'))

    def notify_tv1(self, msg=None):
        self.master.tree_dialog_tv1.message_input(msg)
        return

class SelectedView(tk.Frame):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)
        self.tree_dialog_tv1 = MyTreeview1(self)
        self.tree_dialog_tv2 = MyTreeview2(self)
        self.tree_dialog_tv1.grid(row=0,column=0)
        self.tree_dialog_tv2.grid(row=0,column=1)

if __name__ == "__main__":
    root = tk.Tk()
    selectview = SelectedView(root)
    selectview.pack(fill=tk.BOTH, expand=True)
    root.mainloop()

Now if you double click into the right treeview it gets printes Hello from 2 through the message_input method of the left treeview. Of course you need to tweak this into you current environment, but it shouldn't be too hard for you.

Sign up to request clarification or add additional context in comments.

4 Comments

Hi Thingamabobs. Thanks for the detailed information. It will take a bit of time for me to get my head around this, but no doubt this is a good way to go about it. Just wondering if you know of a simpler solution that doesn't rely on a shared Frame?
@Ant Well, in my point of view it doesn't get much simpler than that. But of course there are many ways to do this. For you, at least in your example, you already have a common master root the code should work just fine without the subclass of tk.Frame. But you could also pass a reference or make class variables and so on, take just what you feel comfortable to work with.
Thanks very much Thingamabobs. I will give that a go and take on the learning curve.
@Ant you are very welcome to do so. It is one of the fundamental things to learn with python and tkinter. In python to use dotted notation to access attributes and the hierarchical structure of tkinter with the master attribute.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.