简体   繁体   English

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

[英]Can I use two different TTK themes in one Tkinter (tk.Tk) root window?

This question concerns Python and Tkinter. 这个问题涉及Python和Tkinter。

I'd like to use two different ttk themes simultaneously, eg 'clam' and 'vista' in one Tkinter window. 我想同时使用两个不同的ttk主题,例如'clam'和'vista'在一个Tkinter窗口中。 So I wrote this: 所以我写了这个:

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

The code loads, however: 但是,代码加载:

  1. I expected the first Button's foreground to be blue and the second Button's foreground to be red, and for two separate themes to be used. 我希望第一个Button的前景为蓝色,第二个Button的前景为红色,并且要使用两个单独的主题。

  2. Instead, both buttons have a red foreground, and both apply the same theme. 相反,两个按钮都有一个红色前景,并且都应用相同的主题。

Is it possible to use two separate ttk themes in one Tkinter program? 是否可以在一个Tkinter程序中使用两个单独的ttk主题?

No, it's not possible, because theme has a global meaning in this context. 不,这是不可能的,因为theme在这种背景下具有全球意义。 You can represent theme as a set of styles for widgets ( for widget layout elements, actually ), you can change style and/or create a new one, but you can't use more than one of themes at the time, because widget's layout depends heavily on it. 您可以将theme表示为窗口小部件的一组样式( 实际上是针对窗口小部件布局元素 ),您可以更改样式和/或创建新样式,但是当时不能使用多个主题,因为窗口小部件的布局很大程度上取决于它。

When you call theme_use('theme_name') tkinter rebuilds all widget's layouts and redraws your entire application , and you can easily check this, thanks to <<ThemeChanged>> virtual event. 当你调用theme_use('theme_name')重建所有小部件的布局并重新 theme_use('theme_name') 整个应用程序 ,并且你可以轻松地检查这一点,这要归功于<<ThemeChanged>>虚拟事件。

Here's a snippet. 这是一个片段。 You will see three prints, caused by each button and by root himself. 您将看到由每个按钮和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()

If you need different foreground for each button - then create a new style for each of them and use the style parameter: 如果每个按钮需要不同的前景 - 然后为每个按钮创建一个新 style并使用style参数:

Here's an another snippet: 这是另一个片段:

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

Everything is well described here and there . 一切都在这里那里得到很好的描述。

No, it is not possible to use two different themes at the same time. 不,不可能同时使用两个不同的主题。

From the canonical documentation [1] for the function underlying the theme_use method (emphasis added by me): 从规范文档[1]中获取theme_use方法的基础功能(由我添加的重点):

Without an argument the result is the name of the current theme. 没有参数,结果是当前主题的名称。 Otherwise this command sets the current theme to themeName, and refreshes all widgets. 否则,此命令将当前主题设置为themeName,并刷新所有小部件。

Here is a simple example showing how you can switch themes on the fly: 这是一个简单的示例,展示了如何动态切换主题:

# 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()

No. You can't use two different themes. 不可以。您不能使用两个不同的主题。 But, you can create a style: 但是,您可以创建一个样式:

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

You can create another style for a different widget 您可以为其他窗口小部件创建另一种样式

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM