-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathMultiColumnListbox.py
63 lines (53 loc) · 2.66 KB
/
MultiColumnListbox.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
try:
import Tkinter as tk
import tkFont
import ttk
except ImportError: # Python 3
import tkinter as tk
import tkinter.font as tkFont
import tkinter.ttk as ttk
class MultiColumnListbox(object):
"""Use a ttk.TreeView as a multicolumn ListBox"""
def __init__(self, headers, data=None, sortable=True, scrollbars_on_overflow=False, autowidth_on_add=False, master=None, **kw):
self.container = tk.Frame(master)
self.container.pack(fill="both", expand=True)
self.tree = ttk.Treeview(master, columns=headers, show="headings", **kw)
if not scrollbars_on_overflow:
self.tree.pack(fill="both", expand=True, in_=self.container)
else:
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_=self.container)
vsb.grid(column=1, row=0, sticky='ns', in_=self.container)
hsb.grid(column=0, row=1, sticky='ew', in_=self.container)
self.container.grid_columnconfigure(0, weight=1)
self.container.grid_rowconfigure(0, weight=1)
for iCol,col in enumerate(headers):
on_sort = (lambda c=iCol: self.sortby(c)) if sortable else ''
self.tree.heading(iCol, text=col, command=on_sort)
self.tree.column(iCol, width=tkFont.Font().measure(col)) # Adjust the column's width to the header string
self.autowidth_on_add = autowidth_on_add
if data is not None:
for item in data:
self.add_item(item)
def autowidth(self, new_item):
for iCol, val in enumerate(new_item):
if val is None: continue
col_w = tkFont.Font().measure(val)
if self.tree.column(iCol, width=None) < col_w:
self.tree.column(iCol, width=col_w)
def add_item(self, new_item):
self.tree.insert('', 'end', values=new_item)
if self.autowidth_on_add:
self.autowidth(new_item)
def sortby(self, iCol, descending=False):
"""sort tree contents when a column header is clicked on"""
# Grab values to sort
data = [(self.tree.set(child, iCol), child) for child in self.tree.get_children('')]
# Sort the data in place
data.sort(reverse=descending)
for iRow, item in enumerate(data):
self.tree.move(item[1], '', iRow)
# Switch the heading so it will sort in the opposite direction
self.tree.heading(iCol, command=lambda c=iCol: self.sortby(c, not descending))