Display Listbox with columns using Tkinter?
You can use Ttk/Tkinker Treeview
widget, which is used to work with tabular data.
The following is an example of a class that uses a Treeview
widget to display a multi-column list of strings:
'''Here the TreeView widget is configured as a multi-column listboxwith adjustable column width and column-header-click sorting.'''try: import Tkinter as tk import tkFont import ttkexcept ImportError: # Python 3 import tkinter as tk import tkinter.font as tkFont import tkinter.ttk as ttkclass MultiColumnListbox(object): """use a ttk.TreeView as a multicolumn ListBox""" def __init__(self): self.tree = None self._setup_widgets() self._build_tree() def _setup_widgets(self): s = """\click on header to sort by that columnto change width of column drag boundary """ msg = ttk.Label(wraplength="4i", justify="left", anchor="n", padding=(10, 2, 10, 6), text=s) msg.pack(fill='x') container = ttk.Frame() container.pack(fill='both', expand=True) # create a treeview with dual scrollbars self.tree = ttk.Treeview(columns=car_header, show="headings") vsb = ttk.Scrollbar(orient="vertical", command=self.tree.yview) hsb = ttk.Scrollbar(orient="horizontal", command=self.tree.xview) self.tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set) self.tree.grid(column=0, row=0, sticky='nsew', in_=container) vsb.grid(column=1, row=0, sticky='ns', in_=container) hsb.grid(column=0, row=1, sticky='ew', in_=container) container.grid_columnconfigure(0, weight=1) container.grid_rowconfigure(0, weight=1) def _build_tree(self): for col in car_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 car_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(car_header[ix],width=None)<col_w: self.tree.column(car_header[ix], width=col_w)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 it will sort in the opposite direction tree.heading(col, command=lambda col=col: sortby(tree, col, \ int(not descending)))# the test data ...car_header = ['car', 'repair']car_list = [('Hyundai', 'brakes') ,('Honda', 'light') ,('Lexus', 'battery') ,('Benz', 'wiper') ,('Ford', 'tire') ,('Chevy', 'air') ,('Chrysler', 'piston') ,('Toyota', 'brake pedal') ,('BMW', 'seat')]if __name__ == '__main__': root = tk.Tk() root.title("Multicolumn Treeview/Listbox") listbox = MultiColumnListbox() root.mainloop()
These are some pictures of the result of using a Treeview
widget:
Using TkTreectrl:
import Tkinter as tkimport TkTreectrl as treectrlimport sqlite3def setup_table(connection): cursor=connection.cursor() cursor.execute('''CREATE TABLE foo (id INTEGER PRIMARY KEY AUTOINCREMENT, bar TEXT)''') sql='INSERT INTO foo (bar) values (?)' for i in range(10): cursor.execute(sql,(i,)) cursor.execute(sql,(u'\N{INFINITY}',))def select_cmd(selected): print 'Selected items:', selecteddef main(): connection=sqlite3.connect(':memory:') setup_table(connection) cursor=connection.cursor() root = tk.Tk() root.title('Simple MultiListbox demo') mlb = treectrl.MultiListbox(root) mlb.pack(side='top', fill='both', expand=1) tk.Button(root, text='Close', command=root.quit).pack(side='top', pady=5) mlb.focus_set() mlb.configure(selectcmd=select_cmd, selectmode='extended') mlb.config(columns=('Column 1', 'Column 2')) cursor.execute('SELECT * from foo') for row in cursor.fetchall(): mlb.insert('end',*map(unicode,row)) root.mainloop()if __name__=='__main__': main()
yields