Search code examples
pythontkinterpython-3.7ttk

How to configure ttk.Treeview item color in Python 3.7.3?


I want to customize the style of the sigle items in a ttk.Treeview. Example code:

import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
tree = ttk.Treeview(root)

# Inserted at the root, program chooses id:
tree.insert('', 'end', 'foo', text='Foo', tags=['red_fg'])

# Inserted underneath an existing node:
tree.insert('foo', 'end', text='Bar', tags=['blue_fg'])

# tag's order can be important
tree.tag_configure("red_fg", foreground="red")
tree.tag_configure("blue_fg", foreground="blue")

tree.pack()
root.mainloop()

This is working perfectly in Python 3.6.8 (font is red/blue), but not at all in Python 3.7.3 (font is black). I have tested this in Windows 7 and 10, both in 32 and 64 bit.

How can I get this working in the newer version?


Solution

  • Maybe I'm a bit late here but...

    You're surely facing a known bug affecting Windows Python builds shipping tk v8.6.9.

    To solve, add this code on top of yours (before instantiating the Treeview):

    import tkinter as tk
    import tkinter.ttk as ttk
    
    root = tk.Tk()
    s = ttk.Style()
    
    #from os import name as OS_Name
    if root.getvar('tk_patchLevel')=='8.6.9': #and OS_Name=='nt':
        def fixed_map(option):
            # Fix for setting text colour for Tkinter 8.6.9
            # From: https://core.tcl.tk/tk/info/509cafafae
            #
            # Returns the style map for 'option' with any styles starting with
            # ('!disabled', '!selected', ...) filtered out.
            #
            # style.map() returns an empty list for missing options, so this
            # should be future-safe.
            return [elm for elm in s.map('Treeview', query_opt=option) if elm[:2] != ('!disabled', '!selected')]
        s.map('Treeview', foreground=fixed_map('foreground'), background=fixed_map('background'))