You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MacOS下如何让ttk Treeview标题保持深色模式不受系统切换影响?

问题描述

我使用customtkinter(简称ctk)开发GUI应用,主窗口基于ctk初始化。由于ctk没有Treeview组件,因此采用tkinter ttk的Treeview组件,其父容器为ctk主窗口内的一个frame。我的MacOS系统通常设置为深色模式,但当系统从深色切换到浅色模式时,Treeview组件的标题背景会变为浅色(标题文本仍保持白色),其余元素已实现深色模式的保持,特此寻求解决办法。

原代码如下:

style = ttk.Style()
style.theme_use('aqua')

# Configure the Treeview style
style.configure("Treeview",
                background="#333333",
                foreground="white",
                fieldbackground="#333333",
                bordercolor="#333333",
                borderwidth=1)

style.map('Treeview',
          background=[('selected', 'dark gray')],
          foreground=[('selected', 'white')])

# Configure the Treeview Heading style
style.configure("Treeview.Heading",
                background="#444444",
                foreground="white",
                bordercolor="#444444",
                borderwidth=1,
                relief='flat')

# Redefine the heading style options to ensure it remains dark
style.configure("Custom.Treeview.Heading",
                background="#444444",
                foreground="white",
                bordercolor="#444444",
                relief="flat")

style.map("Custom.Treeview.Heading",
          background=[('active', '#5a5a5a'), ('!active', '#444444')],
          foreground=[('active', 'white'), ('!active', 'white')],
          relief=[('active', 'flat'), ('!active', 'flat')])
解决方案

在MacOS的aqua主题下,Treeview标题的样式会跟随系统外观自动切换,仅通过style.configure无法覆盖系统的动态样式规则。需通过以下两步解决:

  • 为Treeview组件明确指定自定义样式,确保其标题使用我们定义的Custom.Treeview.Heading而非默认样式
  • 覆盖标题样式的所有状态映射,完全固定背景色和文本样式,阻断系统主题的影响

修改后的完整代码:

import tkinter as tk
import customtkinter as ctk
from tkinter import ttk

# 固定ctk应用的深色模式
ctk.set_appearance_mode("dark")
root = ctk.CTk()
root.title("Treeview Dark Mode Persist")

# 创建ctk容器frame
container = ctk.CTkFrame(root)
container.pack(fill="both", expand=True, padx=15, pady=15)

style = ttk.Style()
style.theme_use('aqua')

# 配置Treeview主体深色样式
style.configure("Treeview",
                background="#333333",
                foreground="white",
                fieldbackground="#333333",
                bordercolor="#333333",
                borderwidth=1)

style.map('Treeview',
          background=[('selected', 'dark gray')],
          foreground=[('selected', 'white')])

# 配置自定义标题样式
style.configure("Custom.Treeview.Heading",
                background="#444444",
                foreground="white",
                bordercolor="#444444",
                borderwidth=1,
                relief="flat")

# 覆盖所有状态的映射规则,确保标题样式完全固定
style.map("Custom.Treeview.Heading",
          background=[('active', '#5a5a5a'), ('!active', '#444444'), ('pressed', '#444444')],
          foreground=[('active', 'white'), ('!active', 'white'), ('pressed', 'white')],
          relief=[('active', 'flat'), ('!active', 'flat'), ('pressed', 'flat')])

# 创建Treeview时指定自定义样式"Custom.Treeview"
tree = ttk.Treeview(container, style="Custom.Treeview", columns=("Column1", "Column2"), show="headings")

# 设置列标题
tree.heading("Column1", text="列1")
tree.heading("Column2", text="列2")

# 添加示例数据
tree.insert("", "end", values=("示例数据1", "示例数据2"))
tree.insert("", "end", values=("示例数据3", "示例数据4"))

tree.pack(fill="both", expand=True)

root.mainloop()

关键要点

  1. 指定自定义样式:创建Treeview时必须设置style="Custom.Treeview",这样组件才会关联我们定义的Custom.Treeview.Heading样式,而非默认的系统样式。
  2. 全状态映射覆盖:扩展style.map的状态规则,覆盖active、!active、pressed等所有可能的交互状态,确保任何场景下标题样式都保持深色。
  3. 固定ctk外观模式:通过ctk.set_appearance_mode("dark")保证主窗口和ctk原生组件的深色模式一致性。

内容的提问来源于stack exchange,提问作者afairbridge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:40:55