Method in one Python Treeview Class to affect instance of different Treeview class

Question:

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.

Asked By: Ant

||

Answers:

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.

Answered By: Thingamabobs
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.