关于使用ttk.Style()的问题?

时间:2018-01-30 09:12:08

标签: python tkinter ttk

为了使ttk.Style()类的实例可用,这个tkinter guide中说明了语法是:

import ttk
s=ttk.Style()

在IDLE中输入这些命令时,我注意到ttk.Style()实际上有一个预定义的参数,即

s=ttk.Style(master=None)

我写了以下测试脚本:

import tkinter as tk
import tkinter.ttk as ttk


class App(ttk.Frame):

    def __init__(self, parent):
        ttk.Frame.__init__(self, parent, style='App.TFrame', relief=tk.SUNKEN,
                           border=10)
        self.parent = parent
        self.__createStyle()
        self.__createWidgets()

    def __createStyle(self):
        self.s = ttk.Style()
        self.s.configure('.', background='orange', border=100)
        self.s.configure('App.TFrame', background='yellow')
        self.s.configure('Btn.TButton', background='light blue', border=10)

    def __createWidgets(self):
        self._label = ttk.Label(self.parent, text='Label packed in root.')
        self._label.pack()
        self._btn = ttk.Button(self, style='Btn.TButton', command=self.__click,
            text='Button packed inside self or class App, which is a ttk.Frame')
        self._btn.pack()

    def __click(self):
        return print('Left Button Clicked!')



class myWidget(ttk.Frame):

    def __init__(self, parent):
        ttk.Frame.__init__(self, parent, style='my.TFrame', relief=tk.GROOVE,
                           border=10)
        self.parent = parent
        self.__createStyle()
        self.__createWidgets()

    def __createStyle(self):
        self.s = ttk.Style()
        self.s.configure('my.TFrame', background='purple')
        self.s.configure('my.TLabel', background='pink', border=10)
        self.s.configure('my.TEntry', foreground='red', border=10)

    def __createWidgets(self):
        self._label = ttk.Label(self, style='my.TLabel',
            text='myWidget Label packed in self or class myWidget, which is a ttk.Frame.')

        self._label.pack()
        self._entry = ttk.Entry(self, style='my.TEntry')
        self._entry.pack()



if __name__ == "__main__":
    root = tk.Tk()
    root.title('Test Style')
    root.geometry('500x150')
    a = App(root)
    a.pack(fill='both', expand=1)
    b = myWidget(a)
    b.pack()

    root.mainloop()

问题1:我何时需要在master中声明ttk.Style()辩论?例如。在上面的脚本中,如果我在self.s = ttk.Style()中写self.s = ttk.Style(master=self.parent)class myWidget,我会得到相同的结果(参见图1)。

问题2:是否需要在s=ttk.Style()前加self前缀?我得到的结果如图1所示,带有和不带self前缀。

问题3:如果我将myWidget类中的'my.TFrame'重命名为'App.TFrame'(此名称用于class App),class App的背景颜色1}}也改为紫色(与class myWidget颜色相同。为什么在不同类中的变量名是唯一的时候会发生这种情况?

问题4:名称'App.TFrame''my.TFrame'在声明之前被调用。为什么python或tkinter没有抱怨或给出错误但允许脚本执行?

Fig1

图1

Fig2

图2

2 个答案:

答案 0 :(得分:4)

  

我何时需要在master声明ttk.Style()辩论?

除了tkinter不支持default root的情况外,可能永远不会。当您将None作为主服务器传递时,主服务器将成为root类的当前Tk实例。

masterroot或任何tk - 小部件)的主要目的是将tk的实例委托给Style,以便Style可以执行Tcl相关命令。

不多也不少。

  

是否需要在s=ttk.Style()前加上self

这取决于您的要求。在代码的上下文中,self毫无意义,因为您在__createStyle函数的范围内设置样式。

否则,如果您希望保留引用,则使用self.

作为前缀是有意义的
  

如果我将myWidget类中的my.TFrame重命名为App.TFrame(此名称用于class App),则class App的背景颜色也会变为紫色(相同)颜色为class myWidget。为什么这会发生,因为不同类中的变量名是唯一的?

因为两个类共享相同的帧样式,因此颜色相同。创建的样式是一个全局的东西,它可以在运行时进行查找,所有相关的小部件都会对这些chages做出反应。

  

名称App.TFramemy.TFrame在声明之前被调用。为什么python或tkinter没有抱怨或给出错误但允许脚本执行?

为什么你认为他们应该这样做?当您传递<any_sensible_name>.<any_relevant_and_existing_basestyle>之类的内容时,ttk知道您想要基本样式的变体,因此它会隐式创建一个,继承所有基本属性。

尝试一些更无意义的技巧,比如你当前没有点(ttk.Frame.__init__(..., style='AppTFrame', ...))的样式名称,这会给你所需的错误:

_tkinter.TclError: Layout AppTFrame not found

答案 1 :(得分:0)

只是部分回答,但我想@Bryan Oakley迟早会帮助我们。

问题3:
如果在MyWidget类中使用“App.TFrame”而不是“my.TFrame”,则覆盖预定义的样式属性。

简短的例子:
如果您设置"TFrame"样式,则所有"TFrame"(== Tkinter.Frame / ttk.Frame)实例都会受到影响。
这有时也称为“root-Style”。 /> 如果您定义另一个"somename.TFrame"并将其设置为一个类型框架的对象,则它将是"somename.TFrame"的样式。

问题4:
查找名称仅覆盖默认样式。
只要它们没有属性,它们就不会覆盖任何东西 这个“赋值”导致tcl调用,并且在Tkinter / ttk Sources(在BaseWidget类中使用)中没有特定的错误处理。

我只能说tcl不会在这里抛出错误,但我自己也不是tcl专家。

我希望这至少有点帮助。