J'essaie de créer un Listbox
dans tkinter avec des colonnes.
Je retourne à partir d'un disque de requête DB et je voudrais afficher chaque entrée dans sa propre colonne pour chaque enregistrement.
En regardant Listbox
, je me sens comme s'il y avait cette fonctionnalité là-bas mais je ne peux pas le trouver. Quel widget dois-je utiliser pour faire cela? Je cherche autour de vous en ligne mais la documentation a été très clairsemée.
Vous pouvez utiliser TTK/TKinker Treeview
widget, utilisé pour fonctionner avec des données tabulaires.
Ce qui suit est un exemple d'une classe qui utilise un widget Treeview
pour afficher une liste multi-colonnes de chaînes:
'''
Here the TreeView widget is configured as a multi-column listbox
with adjustable column width and column-header-click sorting.
'''
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):
self.tree = None
self._setup_widgets()
self._build_tree()
def _setup_widgets(self):
s = """\click on header to sort by that column
to 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()
Ce sont des images du résultat de l'utilisation d'un widget Treeview
:
Une solution simple consiste à utiliser deux boîtes de liste côte à côte. Il n'y a pas de vraie magie, vous devez simplement faire un peu de travail supplémentaire pour obtenir une barre de défilement pour contrôler les deux (facilement effectué) et avoir la sélection dans les deux synchronisations (aussi facilement effectuées).