pythonpython-3.xtkintertreeviewtkinter-layout

How to define different styles/themes with tkinter


I am learning tkinter and have noticed something with using styles when trying to have different windows or frames with styles.

In the code example I provided, if I change the style attributes on frame2, they also show in frame1. If I change the order of execution then the reverse happens.

How can I define styles that are specific to each frame or window?

Thanks Dan

from tkinter import *
import tkinter as tk
from tkinter import ttk


def showframe1():
    f1_columns = ('#1', '#2')
    f1_tree = ttk.Treeview(frame1, columns=f1_columns, show='headings')

    f1_style = ttk.Style()
    f1_style.theme_use("default")
    f1_style.configure("Treeview",
                        background="white",
                        foreground="black",
                        rowheight=25   # Height of each row in tree
                        )

    f1_tree.heading('#1', text='First Name')
    f1_tree.heading('#2', text='Last Name')
    f1_tree.column("#1", width=150)
    f1_tree.column("#2", width=150)

    # generate sample data
    contacts = []
    for n in range(1, 100):
        contacts.append((f'first {n}', f'last {n}'))

    # adding data to the frame1 tree
    for contact in contacts:
        f1_tree.insert('', tk.END, values=contact)

    f1_tree.grid(row=0, column=0, sticky='nsew')


def showframe2():
    f2_columns = ('#1', '#2', '#3')
    f2_tree = ttk.Treeview(frame2, columns=f2_columns, show='headings')

    f2_style = ttk.Style()
    f2_style.theme_use("default")
    f2_style.configure("Treeview",
                       background="lightblue",
                       foreground="black",
                       rowheight=25  # Height of each row in tree
                       )

    f2_tree.heading('#1', text='First Name')
    f2_tree.heading('#2', text='Last Name')
    f2_tree.heading('#3', text='Email')
    f2_tree.column("#1", width=150)
    f2_tree.column("#2", width=150)
    f2_tree.column("#3", width=250)

    # generate sample data
    contacts = []
    for n in range(1, 100):
        contacts.append((f'first {n}', f'last {n}', f'email{n}@example.com', f'email{n}@example.com'))

    # adding data to the frame2 tree
    for contact in contacts:
        f2_tree.insert('', tk.END, values=contact)

    f2_tree.grid(row=0, column=0, sticky='nsew')

def exit_root(event):
    root.destroy()

root = tk.Tk()
root.title('Frame Styles Example')
root.geometry('600x800')

frame1 = Frame(root, bd=5, relief='sunken')
frame1.grid(row=0, column=0, padx=20, pady=10, sticky=N + W)

frame2 = Frame(root, bd=5, relief='sunken')
frame2.grid(row=1, column=0, padx=20, pady=10, sticky=N + W)

showframe1()
showframe2()

root.bind('<Return>', exit_root)

# run the app
root.mainloop()

Solution

  • I found a good tutorial at https://www.pythontutorial.net/tkinter/ttk-style/

    I needed to create a custom Treeview style for the additional frame(s). I just created two custom styles.

    f1_style.configure("f1.Treeview",....) f2_style.configure("f2.Treeview",....)

    Then assign the style to each Treeview definition. ttk.Treeview(frame1, columns=f1_columns, show='headings',style='f1.Treeview') ttk.Treeview(frame2, columns=f2_columns, show='headings',style='f2.Treeview')

    With this, I can control the style of each frame.