为了使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没有抱怨或给出错误但允许脚本执行?
图1
图2
答案 0 :(得分:4)
我何时需要在
master
声明ttk.Style()
辩论?
除了tkinter
不支持default root
的情况外,可能永远不会。当您将None
作为主服务器传递时,主服务器将成为root
类的当前Tk
实例。
master
(root
或任何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.TFrame
和my.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专家。
我希望这至少有点帮助。