Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tkinter Treeview heading styling

I want to change the background colour of the treeview headings. I have identified the element option of the Treeview.Heading layout responsible for this: Treeheading.cell. The problem is that this setting does not work on the 'vista' theme (Due to drawing issues I assume).

working code (theme looks terrible though):

from tkinter import *
from tkinter import ttk

p=Tk()

separator = PanedWindow(p,bd=0,bg="#202322",sashwidth=2)

separator.pack(fill=BOTH, expand=1)

_frame = Frame(p,bg="#383838")

t=ttk.Treeview(_frame)

t["columns"]=("first","second")
t.column("first",anchor="center" )
t.column("second")
t.heading("first",text="first column")
t.heading("second",text="second column")
t.insert("",0,"dir1",text="directory 1")
t.insert("dir1","end","dir 1",text="file 1 1",values=("file 1 A","file 1 B"))
id=t.insert("","end","dir2",text="directory 2")
t.insert("dir2","end",text="dir 2",values=("file 2 A","file 2 B"))
t.insert(id,"end",text="dir 3",values=("val 1 ","val 2"))
t.insert("",0,text="first line",values=("first line 1","first line 2"))
t.tag_configure("ttk",foreground="black")

ysb = ttk.Scrollbar(orient=VERTICAL, command= t.yview)
xsb = ttk.Scrollbar(orient=HORIZONTAL, command= t.xview)
t['yscroll'] = ysb.set
t['xscroll'] = xsb.set

print(ttk.Style().theme_names())

ttk.Style().theme_use('default')


ttk.Style().configure("Treeview", background="#383838",foreground="white")
ttk.Style().configure("Treeview.Heading",background = "blue",foreground="Black")
p.configure(background='black')

t.grid(in_=_frame, row=0, column=0, sticky=NSEW)
ysb.grid(in_=_frame, row=0, column=1, sticky=NS)
xsb.grid(in_=_frame, row=1, column=0, sticky=EW)
_frame.rowconfigure(0, weight=1)
_frame.columnconfigure(0, weight=1)

separator.add(_frame)

w = Text(separator)
separator.add(w)

p.mainloop()

my attempt using 'vista' theme:

ttk.Style().element_create("Treeheading.cell","from","default")

ttk.Style().configure("Treeview", background="#383838",foreground="white")
ttk.Style().configure("Treeview.Heading",background = "Blue")

element_create has worked in other instances of this problem but with different widgets. Thank you, any help would be appreciated.

working in python 3. Also the code is not mine, I found it and used it to test.

like image 455
Ukfeneley Avatar asked Mar 10 '17 00:03

Ukfeneley


1 Answers

You are on the right track but need to change the border element rather than the cell element. As you are working on Windows, the treeview cells are being displayed using a system provided theme element from the Visual Styles API. In this case it is a HP_HEADERITEM part from the HEADER class. As this is drawn by the system theme engine you don't get to customise it from Tk aside from selecting alternate looks according to the state.

If you must customise the look of the header then you have to replace the theme part with one that Tk can customise and the default theme is a good choice. I would also recommend that you define this as a custom style so that you can re-style specific widgets and not necessarily all of them.

style = ttk.Style()
style.element_create("Custom.Treeheading.border", "from", "default")
style.layout("Custom.Treeview.Heading", [
    ("Custom.Treeheading.cell", {'sticky': 'nswe'}),
    ("Custom.Treeheading.border", {'sticky':'nswe', 'children': [
        ("Custom.Treeheading.padding", {'sticky':'nswe', 'children': [
            ("Custom.Treeheading.image", {'side':'right', 'sticky':''}),
            ("Custom.Treeheading.text", {'sticky':'we'})
        ]})
    ]}),
])
style.configure("Custom.Treeview.Heading",
    background="blue", foreground="white", relief="flat")
style.map("Custom.Treeview.Heading",
    relief=[('active','groove'),('pressed','sunken')])

What we are doing is defining a new widget style using the same layout as for the standard treeview style and replacing the border element. While we have not defined the other custom elements, these are looked up hierarchically so in the absence of a Custom.Treeheading.text it will use a Treeheading.text. To use this, we set the style of the treeview widget:

t=ttk.Treeview(_frame, style="Custom.Treeview")

Ends up looking like this on Windows 10:

screenshot of custom treeview

like image 173
patthoyts Avatar answered Nov 11 '22 06:11

patthoyts