Welcome, guest | Sign In | My Account | Store | Cart
# encoding: utf-8
# Author: Miguel Martinez Lopez
# Uncomment the next line to see my email
# print("Author's email: ", "61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex"))

try:
    from Tkinter import Frame, BOTH ,W, CENTER
    from tk import Treeview
except ImportError:
    from tkinter import Frame, BOTH ,W, CENTER
    from tkinter.ttk import Treeview

class TreeView_Table(Frame):

    def __init__(self, parent, columns, anchor_heading = CENTER, anchor_data = W, style=None, xscrollcommand=None, yscrollcommand=None, height=None, padding=None, selectmode=None, onselect=None):

        Frame.__init__(self, parent, class_="TreeView_Table")

        treeview_kwargs = {}
        if style is not None:
            treeview_kwargs["style"] = style
            
        if xscrollcommand is not None:
            treeview_kwargs["xscrollcommand"] = xscrollcommand
            
        if yscrollcommand is not None:
            treeview_kwargs["yscrollcommand"] = yscrollcommand
            
        if height is not None:
            treeview_kwargs["height"] = height
            
        if padding is not None:
            treeview_kwargs["padding"] = padding
        
        if selectmode is not None:
            treeview_kwargs["selectmode"] = selectmode

        self.treeview = Treeview(self,columns=range(1,len(columns)), **treeview_kwargs)
        self.treeview.pack(expand=True, fill=BOTH)
        
        if onselect is not None:
            self.on_select = onselect
            self.treeview.bind("<<TreeviewSelect>>", self._on_select)

        self.treeview.heading("#0", text=columns[0], anchor=anchor_heading)
        self.treeview.column("#0", anchor=anchor_data)
        
        self._columns = columns
        self._number_of_columns = len(columns)

        for i in range(1,len(columns)):
            column_name = "#"+str(i)

            self.treeview.heading(column_name, text=columns[i], anchor=anchor_heading)
            self.treeview.column(column_name, anchor=anchor_data)

    def add_row(self, data):
        if len(data) == self._number_of_columns:
            self.treeview.insert('', 'end', text=data[0], values=data[1:])
        else:
            raise ValueError("The table has %d"%len(self._columns))
            
    def edit_row(self, index, data):
        try:
            item = self.treeview.get_children()[index]
        except IndexError:
            raise ValueError("Index out of range: %d"%index)
            
        if len(data) == len(self._columns):
            self.treeview.item(item, text=data[0], values=data[1:])
        else:
            raise ValueError("The table has only %d columns!"%len(self._columns))
            
    def delete_row(self, index):
        try:
            item = self.treeview.get_children()[index]
        except IndexError:
            raise ValueError("Index out of range: %d"%index)
        
        self.treeview.delete(item)
        
    def clear(self):
        # Another possibility:
        #  self.treeview.delete(*self.treeview.get_children())

        for row in self.treeview.get_children():
            self.treeview.delete(row)
            
    def edit(self, *data):
        self.clear()

        for row in data:
            self.add_row(row)
            
    def focus(self, row=None):
        if row is None:
            return self.treeview.item(self.treeview.focus())
        else:
            item = self.treeview.get_children()[row]
            self.treeview.focus(item)

    def state(self, stateSpec=None):
        if stateSpec is None:
            return self.treeview.state()
        else:
            self.treeview.state(stateSpec)
    
    def xview(self, *args):
        self.treeview.xview(*args)

    def yview(self):
        self.treeview.yview(*args)

    @property
    def number_of_rows(self):
        return len(self.treeview.get_children())
        
    @property
    def number_of_columns(self):
        return self._number_of_columns
        
    def select(self, *rows):
        if len(rows) ==0:
            return self.selected_rows
        else:
            list_of_items = self.treeview.get_children()
            self.treeview.selection_set(*[list_of_items[row] for row in rows])

    @property
    def selected_rows(self):
        data = []
        for idx in self.treeview.selection():
            data_row = self._item_idx_to_row_data(idx)
            data.append(data_row)
        
        return data

    def _on_select(self, event):
        for idx in event.widget.selection():
            data_row = self._item_idx_to_row_data(idx)
            self.on_select(data_row)

    def _item_idx_to_row_data(self, idx):
        item = self.treeview.item(idx)
        return [item["text"]] + item["values"]

if __name__ == '__main__':
    try:
        from Tkinter import Tk
        import tkMessageBox as messagebox
    except ImportError:
        from tkinter import Tk
        from tkinter import messagebox

    root = Tk()
    
    def on_select(data):
        print(data)
        
    def show_info(msg):
        messagebox.showinfo("Table Data", msg)
        
    simple_table = TreeView_Table(root, ["column one","column two", "column three"], onselect=on_select)
    simple_table.pack()
    
    simple_table.add_row([1,2,3])
    show_info("""simple_table.add_row([1,2,3])""")

    simple_table.edit_row(0, [4,5,6])
    show_info("""simple_table.edit_row(0, [4,5,6])""")
    
    simple_table.edit([1,2,3], [4,5,6])
    show_info("""simple_table.edit([1,2,3], [4,5,6])""")
    
    simple_table.select(0)
    show_info("""simple_table.select(0)""")
    
    print(simple_table.selected_rows)
    
    root.mainloop()

History