【问题标题】:Can I use two different TTK themes in one Tkinter (tk.Tk) root window?我可以在一个 Tkinter (tk.Tk) 根窗口中使用两个不同的 TTK 主题吗?
【发布时间】:2017-06-07 18:39:09
【问题描述】:

这个问题涉及 Python 和 Tkinter。

我想同时使用两个不同的 ttk 主题,例如'clam' 和 'vista' 在一个 Tkinter 窗口中。所以我写了这个:

import tkinter as tk
import tkinter.ttk as ttk

class GUI(tk.Tk):

    def __init__(self):

        super().__init__()
        Button_v1()
        Button_v2()


class Button_v1(ttk.Button):

    def __init__(self, default_text="Test"):

        super().__init__(text=default_text)

        s = ttk.Style()
        s.theme_use('clam')
        s.configure(self.winfo_class(), foreground='blue')
        self.pack()


class Button_v2(ttk.Button):

    def __init__(self, default_text="Test2"):

        super().__init__(text=default_text)

        s2 = ttk.Style()
        s2.theme_use('vista')
        s2.configure(self.winfo_class(), foreground='red')
        self.pack()


GUI().mainloop()

代码加载,但是:

  1. 我预计第一个 Button 的前景为蓝色,第二个 Button 的前景为红色,并且使用两个单独的主题。

  2. 相反,两个按钮都有红色前景,并且都应用相同的主题。

是否可以在一个 Tkinter 程序中使用两个单独的 ttk 主题?

【问题讨论】:

  • 你不能那样做。但是,您可以在运行时更改它。

标签: python tkinter


【解决方案1】:

不,这是不可能的,因为theme 在这种情况下具有全局意义。您可以将 theme 表示为小部件的一组样式 (for widget layout elements, actually),您可以更改样式和/或创建新样式,但您不能同时使用多个主题,因为小部件的布局取决于非常重视它。

当您调用 theme_use('theme_name') 时,tkinter 会重建所有小部件的布局和 redraws your entire application,并且您可以轻松检查这一点,这要归功于 <<ThemeChanged>> 虚拟事件。

这是一个sn-p。您将看到三个打印件,由每个按钮和 root 自己造成。

try:
    import tkinter as tk
    import tkinter.ttk as ttk
except ImportError:
    import Tkinter as tk
    import ttk


class GUI(tk.Tk):
    def __init__(self):
        super().__init__()
        self.bind('<<ThemeChanged>>', lambda event: print('theme changed in root and across all widgets!'))
        Button_v1()
        Button_v2()


class Button_v1(ttk.Button):
    def __init__(self, default_text="Test"):
        super().__init__(text=default_text)
        s = ttk.Style()
        s.theme_use('clam')
        s.configure(self.winfo_class(), foreground='blue')
        self.pack()


class Button_v2(ttk.Button):
    def __init__(self, default_text="Test2"):
        super().__init__(text=default_text)
        s2 = ttk.Style()
        s2.theme_use('vista')
        s2.configure(self.winfo_class(), foreground='red')
        self.pack()

GUI().mainloop()

如果您需要为每个按钮设置不同的前景 - then create a new style 为每个按钮使用style 参数:

这是另一个sn-p:

try:
    import tkinter as tk
    import tkinter.ttk as ttk
except ImportError:
    import Tkinter as tk
    import ttk


class GUI(tk.Tk):
    def __init__(self):
        super().__init__()

        s = ttk.Style()
        s.configure('blue.TButton', foreground='blue')
        s.configure('red.TButton', foreground='red')

        Button_v1()
        Button_v2()


class Button_v1(ttk.Button):
    def __init__(self, default_text="Test"):
        super().__init__(text=default_text, style='blue.TButton')
        self.pack()


class Button_v2(ttk.Button):
    def __init__(self, default_text="Test2"):
        super().__init__(text=default_text, style='red.TButton')
        self.pack()

GUI().mainloop()

herethere 的一切都得到了很好的描述。

【讨论】:

    【解决方案2】:

    不,不能同时使用两个不同的主题。

    来自[1] 方法基础函数的规范文档theme_use(重点由我添加):

    如果没有参数,结果是当前主题的名称。否则,此命令会将当前主题设置为 themeName,并刷新所有小部件。

    这是一个简单的示例,展示了如何动态切换主题:

    # python  2
    import Tkinter as tk
    import ttk
    
    # python 3
    #import tkinter as tk
    #import tkinter.ttk as ttk
    
    def switch_theme(theme):
        style = ttk.Style()
        style.theme_use(theme)
    
    root = tk.Tk()
    
    style = ttk.Style()
    for theme in style.theme_names():
        button = ttk.Button(root, text=theme,
                            command=lambda theme=theme: switch_theme(theme))
        button.pack(side="top", padx=4, pady=4)
    
    root.mainloop()
    

    【讨论】:

    • 谢谢。此外,在上面的代码中,按钮的前景色没有改变——它们都是红色的,即使它们基于两种不同的样式(标记为ss2)据说是红色/蓝色。这是否意味着每个 Tkinter 程序只能使用 一个 组样式?
    • @anonnoir:不,您可以在样式之间切换。您一次只能使用一个,但您可以在运行时切换它们。
    • 我明白了。所以这意味着我可以“储存”两种或三种不同的风格(s=ttk.Style() 的变体),并在事件发生时激活它们?我不知道这是可能的。
    【解决方案3】:

    没有。您不能使用两个不同的主题。但是,您可以创建样式:

    style = ttk.Style()
    style.configure("BW.TLabel", foreground="black", background="white")
    
    l1 = ttk.Label(text="Test", style="BW.TLabel")
    l2 = ttk.Label(text="Test", style="BW.TLabel")
    

    您可以为不同的小部件创建另一种样式

    【讨论】:

      猜你喜欢
      • 2021-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多