1,105,281 Community Members

Multiple TreeViews formatting in tkinter

Member Avatar
Rod53718
Newbie Poster
9 posts since Jan 2013
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 
#McListBox Example
#Jan.20, 2013


import tkinter as tk
import tkinter.font as tkFont
import tkinter.ttk as ttk
#import re
Actors_list = [("Rowan","Atkinson"),("John","Candy"),("Morgan","Freeman"),("James","Garner"),("Cary","Grant"),("Kate","Hudson"),
("Jack","Nicholson"),("William","Powell"),("Arnold","Schwarzenegger"),("Tom","Selleck"),("John","Wayne")]

Movies_list = [[("Bean","1997"),("Mr. Bean's Holiday","2007"),("The Lion King","1994"),("Johnny English","2003"),("Johnny English Reborn","2011"),("Keeping Mum","2005"),("The Black Adder","1982-1983")],
[("Dr. Zonk and the Zunkins","1974"),("Tunnel Vision","1976"),("SCTV","1976-1979"),("1941","1979")],
[("The Pawnbroker","1964"),("Blade","1973"),("The Electric Company","1971-1977"),("Attica","1980"),
("Brubaker","1980"),("Street Smart","1980"),("Driving Miss Daisy","1989"),("Glory","1989"),("Unforgiven","1992"),
("Outbreak","1995"),("Se7en","1995"),("Amistad","1997"),("The Bucket List","2007")],
[("Cash McCall","1960"),("Sugarfoot","1957"),("Cheyenne","1955-1957"),("Maverick","1957-1962"),("The Great Escape","1963")],
[("Singapore Sue","1932"),("She Done Him Wrong","1933"),("I'm No Angel","1933"),("Born to be Bad","1934")],
[("200 Cigarettes","1999"),("Almost Famous","2000"),("How to Lose a Guy in 10 Days","2003")],
[("The Cry Baby Killer","1958"),("Seahunt","1961"),("Easy Rider","1969"),("One Flew Over the Cuckoo's Nest","1975")],
[("Mr. Roberts","1955"),("Ziegfeld Follies","1945"),("Manhattan Melodrama","1934"),("The Thin Man","1934")],
[("Hercules in New York","1969"),("Conan the Barbarian","1982"),("The Terminator","1984")],
[("The Rockford Files","1978-1979"),("The Sacketts","1979"),("Magnum, P.I.","1980-1988"),("Blue Bloods","2010-")],
[("The Shootist","1976"),("McQ","1974"),("The Cowboys","1972"),("Brown of Harvard","1926")]]
actor_header = ['First Name','Last Name']
movie_header = ['Movie','Date']

class McListBox(object):
    """use a ttk.TreeView as a multicolumn ListBox"""
    def __init__(self,element_header,element_list):
        self.element_header = element_header
        self.element_list = element_list
        self.tree = None
        self._setup_widgets()
        self._build_tree()

    def _setup_widgets(self):
        container = ttk.Frame()
        container.pack(fill='both', expand=True)
        # create a treeview with scrollbar
        self.tree = ttk.Treeview(columns=self.element_header, show="headings")
        vsb = ttk.Scrollbar(orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=vsb.set)
        self.tree.grid(column=0, row=0, sticky='nsew', in_=container)
        vsb.grid(column=1, row=0, sticky='ns', in_=container)
        container.grid_columnconfigure(0, weight=1)
        container.grid_rowconfigure(0, weight=1)
        self.tree.bind( "<Double-Button-1>", self.OnClick)

    def _build_tree(self):
        for col in self.element_header:
            self.tree.heading(col, text=col.title(),
                command=lambda c=col: sortby(self.tree, c, 0))
            # adjust the column's width to the header string
            self.tree.column(col, width=tkFont.Font().measure(col.title()))
        for item in self.element_list:
            self.tree.insert('', 'end', values=item)
            # adjust column's width if necessary to fit each value
            for ix, val in enumerate(item):
                col_w = tkFont.Font().measure(val)
                if self.tree.column(self.element_header[ix], width=None) < col_w:
                    self.tree.column(self.element_header[ix], width=col_w)

    def OnClick(self, event):
        global return_index
        item = self.tree.identify('item',event.x,event.y)
        return_index = (int((item[1:4]),16) - 1)
        reload_tree(return_index,self)

def isnumeric(s):
    """test if a string is numeric"""
    for c in s:
        if c in "1234567890-.":
            numeric = True
        else:
            return False
    return numeric

def change_numeric(data):
    """if the data to be sorted is numeric change to float"""
    new_data = []
    if isnumeric(data[0][0]):
        # change child to a float
        for child, col in data:
            new_data.append((float(child), col))
        return new_data
    return data

def sortby(tree, col, descending):
    """sort tree contents when a column header is clicked on"""
    # grab values to sort
    data = [(tree.set(child, col), child) for child in tree.get_children('')]
    # if the data to be sorted is numeric change to float
    data = change_numeric(data)
    # now sort the data in place
    data.sort(reverse=descending)
    for ix, item in enumerate(data):
        tree.move(item[1], '', ix)
    # switch the heading so that it will sort in the opposite direction
    tree.heading(col,
        command=lambda col=col: sortby(tree, col, int(not descending)))

def reload_tree(tree_index,source_tree):
    if source_tree == actor_listbox:
        movie_listbox.tree.grid_forget()
        movie_listbox.__init__(movie_header,Movies_list[tree_index])
    elif source_tree == movie_listbox:
        pass

root = tk.Tk()
root.wm_title("ttk.TreeView as multicolumn ListBox")
actor_listbox = McListBox(actor_header,Actors_list)
movie_listbox = McListBox(movie_header,Movies_list[0])

root.mainloop()

def main():
    pass

if __name__ == '__main__':
    main()

I'm fairly new to python and am having problems getting multiple TreeViews to work well. The second tree should change with the mouse selection in the first. Every time I make a selection in the first, padding is extended between the widgets. Is there a way to empty the second one and reload it?

Member Avatar
Rod53718
Newbie Poster
9 posts since Jan 2013
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
1
 

Finally got it to work using "delete"

#McListBox Example
#Jan.20, 2013


import tkinter as tk
import tkinter.font as tkFont
import tkinter.ttk as ttk
#import re
Actors_list = [("Rowan","Atkinson"),("John","Candy"),("Morgan","Freeman"),("James","Garner"),("Cary","Grant"),("Kate","Hudson"),
("Jack","Nicholson"),("William","Powell"),("Arnold","Schwarzenegger"),("Tom","Selleck"),("John","Wayne")]

Movies_list = [[("Bean","1997"),("Mr. Bean's Holiday","2007"),("The Lion King","1994"),("Johnny English","2003"),("Johnny English Reborn","2011"),("Keeping Mum","2005"),("The Black Adder","1982-1983")],
[("Dr. Zonk and the Zunkins","1974"),("Tunnel Vision","1976"),("SCTV","1976-1979"),("1941","1979")],
[("The Pawnbroker","1964"),("Blade","1973"),("The Electric Company","1971-1977"),("Attica","1980"),
("Brubaker","1980"),("Street Smart","1980"),("Driving Miss Daisy","1989"),("Glory","1989"),("Unforgiven","1992"),
("Outbreak","1995"),("Se7en","1995"),("Amistad","1997"),("The Bucket List","2007")],
[("Cash McCall","1960"),("Sugarfoot","1957"),("Cheyenne","1955-1957"),("Maverick","1957-1962"),("The Great Escape","1963")],
[("Singapore Sue","1932"),("She Done Him Wrong","1933"),("I'm No Angel","1933"),("Born to be Bad","1934")],
[("200 Cigarettes","1999"),("Almost Famous","2000"),("How to Lose a Guy in 10 Days","2003")],
[("The Cry Baby Killer","1958"),("Seahunt","1961"),("Easy Rider","1969"),("One Flew Over the Cuckoo's Nest","1975")],
[("Mr. Roberts","1955"),("Ziegfeld Follies","1945"),("Manhattan Melodrama","1934"),("The Thin Man","1934")],
[("Hercules in New York","1969"),("Conan the Barbarian","1982"),("The Terminator","1984")],
[("The Rockford Files","1978-1979"),("The Sacketts","1979"),("Magnum, P.I.","1980-1988"),("Blue Bloods","2010-")],
[("The Shootist","1976"),("McQ","1974"),("The Cowboys","1972"),("Brown of Harvard","1926")]]
actor_header = ['First Name','Last Name']
movie_header = ['Movie','Date']
movie_index = 2
movie_count = 1
class McListBox(object):
    """use a ttk.TreeView as a multicolumn ListBox"""
    def __init__(self,element_header,element_list):
        self.element_header = element_header
        self.element_list = element_list
        self.tree = None
        self._setup_widgets()
        self._build_tree()


    def _setup_widgets(self):
        container = ttk.Frame()
        container.pack(fill='both', expand=True)
        # create a treeview with scrollbar
        self.tree = ttk.Treeview(columns=self.element_header, show="headings")
        vsb = ttk.Scrollbar(orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=vsb.set)
        self.tree.grid(column=0, row=0, sticky='nsew', in_=container)
        vsb.grid(column=1, row=0, sticky='ns', in_=container)
        container.grid_columnconfigure(0, weight=1)
        container.grid_rowconfigure(0, weight=1)
        self.tree.bind( "<Double-Button-1>", self.OnClick)

    def _build_tree(self):
        for col in self.element_header:
            self.tree.heading(col, text=col.title(),
                command=lambda c=col: sortby(self.tree, c, 0))
            # adjust the column's width to the header string
            self.tree.column(col, width=tkFont.Font().measure(col.title()))
        for item in self.element_list:
            self.tree.insert('', 'end', values=item)
            # adjust column's width if necessary to fit each value
            for ix, val in enumerate(item):
                col_w = tkFont.Font().measure(val)
                if self.tree.column(self.element_header[ix], width=None) < col_w:
                    self.tree.column(self.element_header[ix], width=col_w)

    def OnClick(self, event):
        global return_index
        item = self.tree.identify('item',event.x,event.y)
        return_index = (int((item[1:4]),16) - 1)
        reload_tree(return_index,self)


def isnumeric(s):
    """test if a string is numeric"""
    for c in s:
        if c in "1234567890-.":
            numeric = True
        else:
            return False
    return numeric

def change_numeric(data):
    """if the data to be sorted is numeric change to float"""
    new_data = []
    if isnumeric(data[0][0]):
        # change child to a float
        for child, col in data:
            new_data.append((float(child), col))
        return new_data
    return data

def sortby(tree, col, descending):
    """sort tree contents when a column header is clicked on"""
    # grab values to sort
    data = [(tree.set(child, col), child) for child in tree.get_children('')]
    # if the data to be sorted is numeric change to float
    data = change_numeric(data)
    # now sort the data in place
    data.sort(reverse=descending)
    for ix, item in enumerate(data):
        tree.move(item[1], '', ix)
    # switch the heading so that it will sort in the opposite direction
    tree.heading(col,
        command=lambda col=col: sortby(tree, col, int(not descending)))

def reload_tree(tree_index,source_tree):
    global movie_index,movie_count
    if source_tree == actor_listbox:
        i = movie_count
        for movies in Movies_list[movie_index]:
            movie_listbox.tree.delete('I' + '%03X' % i)
            i = i + 1
            movie_count = i

        i = 1
        for item in Movies_list[tree_index]:
            movie_listbox.tree.insert('',(i), values=item)
        movie_index = tree_index
        i = i + 1
    elif source_tree == movie_listbox:
        pass

root = tk.Tk()
root.wm_title("Movie McListBox")
actor_listbox = McListBox(actor_header,Actors_list)
movie_listbox = McListBox(movie_header,Movies_list[movie_index])

root.mainloop()

def main():
    pass

if __name__ == '__main__':
    main()

and "insert"

Question Self-Answered as of 1 Year Ago
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article