[Tkinter-discuss] ttk.Treeview: coloring rows using tags doesn't work with Python 3.7.3

Sibylle Koczian nulla.epistola at web.de
Mon Apr 29 07:16:50 EDT 2019


Hello,

the following script shows a Treeview with names and country codes of 
some towns in Germany. Towns with country code "HE" or "BY" should be 
shown with coloured background, in the case of "BY" additionally with 
white text.

This works using Python 3.5 or 3.6. I seem to remember that it worked 
with earlier versions of Python 3.7, but that's not certain. Using 
Python 3.7.3 all the entries have white background and black text. 
Opening an entry with Enter or double click shows the name of the town 
in the Entry field, together with the country name, if the row has the 
tag for HE or BY. So the entries have the tags they should, but the 
color doesn't change.

Changing the font of an entry using tags does work.

All of these Python versions come with tcl/tk version 8.6, but I don't 
know the patch numbers, they probably changed. The official 
documentation for tkinter and for tcl/tk seems to show that the script 
is correct. I can see no hint of recent changes in the use of tags, 
tag_configure and the options usable with tags.

Here is the script:

############################################################################

#!/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()



More information about the Tkinter-discuss mailing list