ttk.Treeview: Farbe für einzelne Zeilen geht nicht wie erwartet
Verfasst: Samstag 27. April 2019, 15:33
Ich stehe gerade mal fest auf dem Schlauch. Nach allem, was ich in Lehrbuch, tkinter-Dokumentation und per Suchmaschine finden kann, müsste das folgende Beispielprogramm hessische und bayerische Städte in der Treeview-Komponente farblich kennzeichnen. Es denkt aber gar nicht daran.
Das Eingabefeld unten zeigt die entsprechenden Städte richtig mit Bundesland an (Doppelklick oder Enter-Taste). Daraus schließe ich, dass das Vergeben der tags richtig funktioniert, es hat nur nicht die Wirkung, für die tag_configure eigentlich sorgen sollte.
Wo liegt mein Fehler? Ersetzen der Farbnamen durch RGB-Werte habe ich ausprobiert, das hat nichts geändert. Ich habe auch versuchsweise die Aufrufe von treeview.tag_configure(...) an das Ende der Methode populate(...) verlagert, so dass die Daten vorher in den treeview kamen. Auch kein Unterschied.
Python 3.7.3, Windows 10. Mit ArchLinux und LXQt als Desktop gleiches Ergebnis.
Das Eingabefeld unten zeigt die entsprechenden Städte richtig mit Bundesland an (Doppelklick oder Enter-Taste). Daraus schließe ich, dass das Vergeben der tags richtig funktioniert, es hat nur nicht die Wirkung, für die tag_configure eigentlich sorgen sollte.
Code: Alles auswählen
#!/usr/bin/env python3
# treeview_forum.py
"""Treeview-Komponente erforschen"""
import tkinter as tk
from tkinter import ttk
CITIES = [
"1,Frankfurt,HE",
"2,Augsburg,BY",
"3,Kiel,SH",
"4,Flensburg,SH",
"5,Stuttgart,BW"
]
class TreeFrame(ttk.Frame):
column_defs = {
"#0": {"label": "IDN", "width": 40, "anchor": tk.E},
"Name": {"label": "Name", "minwidth": 200, "stretch": True},
"Country": {"label": "CC", "width": 80}
}
default_width = 100
default_minwidth = 10
default_anchor = tk.W
def __init__(self, parent, export_city, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.export_namecolumn = export_city
self.treeview = ttk.Treeview(self,
columns=["Name", "Country"],
selectmode='browse')
for (name, definition) in self.column_defs.items():
label = definition.get('label', '')
anchor = definition.get('anchor', self.default_anchor)
minwidth = definition.get('minwidth', self.default_minwidth)
width = definition.get('width', self.default_width)
stretch = definition.get('stretch', False)
self.treeview.heading(name, text=label, anchor=anchor)
self.treeview.column(name, anchor=anchor, minwidth=minwidth,
width=width, stretch=stretch)
self.treeview.tag_configure('hessen', background='lightgreen')
self.treeview.tag_configure('bayern', background='darkgray',
foreground='white')
self.treeview.bind('<<TreeviewOpen>>', self.on_open_record)
self.scrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL,
command=self.treeview.yview)
self.treeview.configure(yscrollcommand=self.scrollbar.set)
self.treeview.grid(row=0, column=0, sticky='NSEW')
self.scrollbar.grid(row=0, column=1, sticky='NSW')
def on_open_record(self, *args):
selected_item = self.treeview.selection()[0]
selected_name = self.treeview.set(selected_item, 0)
in_hessen = (" (Hessen)"
if self.treeview.tag_has('hessen', selected_item) else "")
in_bayern = (" (Bayern)"
if self.treeview.tag_has('bayern', selected_item) else "")
msg = "{0}{1}{2}".format(selected_name, in_hessen, in_bayern)
self.export_namecolumn(msg)
def populate(self, rows):
"""Clear the treeview & write the supplied data rows to it."""
for row in self.treeview.get_children():
self.treeview.delete(row)
for rec in rows:
idstr = str(rec['ID'])
values = [rec['Name'], rec['CC']]
if rec['CC'] == 'HE':
cc = 'hessen'
elif rec['CC'] == 'BY':
cc = 'bayern'
else:
cc = ''
self.treeview.insert('', 'end', iid=idstr, text=idstr,
values=values, tags=(cc,))
if rows:
self.treeview.focus_set()
first = self.treeview.identify_row(0)
self.treeview.selection_set(first)
self.treeview.focus(first)
class RecordFrame(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
ttk.Label(self, text="Ausgewählt:").grid(row=0, column=0)
self.entryvar = tk.StringVar()
ttk.Entry(self, textvariable=self.entryvar).grid(row=1, column=0,
sticky='EW')
def set(self, value):
self.entryvar.set(value)
def get(self):
return self.entryvar.get()
class Application(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.geometry("360x500")
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.recordlist = TreeFrame(self, self.show_city)
self.recordlist.grid(row=0, padx=10, pady=10, sticky="NSEW")
self.dataframe = RecordFrame(self)
self.dataframe.grid(row=1, padx=10, pady=10, sticky="NSEW")
self.recordlist.populate(self.get_all_cities(CITIES))
def get_all_cities(self, citynames):
fieldnames = ("ID", "Name", "CC")
allcities = [dict(zip(fieldnames, row.split(','))) for row in citynames]
return allcities
def show_city(self, city):
self.dataframe.set(city)
root = Application()
root.mainloop()
Python 3.7.3, Windows 10. Mit ArchLinux und LXQt als Desktop gleiches Ergebnis.