我可以在一个Tkinter(tk.Tk)根窗口中使用两个不同的TTK主题吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我可以在一个Tkinter(tk.Tk)根窗口中使用两个不同的TTK主题吗?相关的知识,希望对你有一定的参考价值。

这个问题涉及Python和Tkinter。

我想同时使用两个不同的ttk主题,例如'蛤蜊'和'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主题?

答案

不,这是不可能的,因为theme在这方面具有全球意义。您可以将theme表示为小部件的一组样式(for widget layout elements, actually),您可以更改样式和/或创建新样式,但是当时不能使用多个主题,因为小部件的布局在很大程度上取决于它。

当你调用theme_use('theme_name') tkinter重建所有小部件的布局和redraws your entire application时,你可以轻松地检查这一点,感谢<<ThemeChanged>>虚拟事件。

这是一个片段。您将看到由每个按钮和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参数:

这是另一个片段:

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

另一答案

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

从规范文档[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()
另一答案

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

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")

您可以为其他窗口小部件创建另一种样式

以上是关于我可以在一个Tkinter(tk.Tk)根窗口中使用两个不同的TTK主题吗?的主要内容,如果未能解决你的问题,请参考以下文章

Tkinter界面编程----函数分析

删除 Tkinter 窗口上的 TK 图标

python学习tkinter(1-3)

Tkinter 在 Mac 上的 Tk() 上不断崩溃

tkinter_一个简单的窗口

展开 Tkinter 框架