五笔打字通主页
今天开始讲解一下TTK基本知识,我们前面讲了不少组件,这个组件都是tkinter模块里的组件,这些组件在外观上主要是经典风格(经典灰),在外貌协会的人的眼中,这太土了,希望tkinter组件在外观上有所改进,所以,应用户需求,ttk模块来了。
这个ttk模块里除我们前面学的12个组件:Button,Lable,Frame,LabelFrame,Radiobutton,Checkbutton,Entry,Menu,PaneWindow,Scale,Spinbox,Scrollbar 还增加了6个ttk独有的组件:Combobox,Notebook,Progressbar,Separator,Sizegrip,Treeview
ttk组件在外观样式上是跟系统相统一的主题,在外观上好看多了,但要注意,ttk在外观样式的设置上,跟tkinter模块的组件有些不一样,它可以靠ttk的style类来实现,作为后续的ttk模块对tkinter的兼容性并不好,比如,以前我们设置背景颜色bg,前景颜色fg,就不可以用了。
用ttk组件时,当然需要先导入ttk模块。上篇文章有导入ttk模块的说明,下面我再用代码来说明ttk的一些基本知识。
首先来看看tkinter和ttk模块在外观的区别,下面代码对6个组件在2个模块下进入了对比显示,让大家有一个感性认识。
import tkinter as tk import tkinter.ttk as ttk root=tk.Tk() fr1=tk.LabelFrame(root,text='tk.LableFrame') # 不设置边线宽,无法显示 fr1.pack(padx=10,pady=10) fr2=ttk.LabelFrame(root,text='ttk.LableFrame') # 不设置边线宽,无法显示 fr2.pack(padx=10,pady=10) but1=tk.Button(fr1,text="按钮1") but1.pack(side='left',padx=10,pady=10) but2=ttk.Button(fr2,text="按钮2") but2.pack(side='left',padx=10,pady=10) la1=tk.Label(fr1,text='标签1',bg='lightblue') la1.pack(side='left',padx=10,pady=10) la2=ttk.Label(fr2,text='标签2',background='lightblue') la2.pack(side='left',padx=10,pady=10) var1=tk.IntVar() ra1=tk.Radiobutton(fr1,text='单选按钮1',variable=var1,value=1) ra1.pack(side='left',padx=10,pady=10) ra2=ttk.Radiobutton(fr2,text='单选按钮2',variable=var1,value=2) ra2.pack(side='left',padx=10,pady=10) var2=tk.IntVar() ch1=tk.Checkbutton(fr1,text="多选按钮1",variable=var1) ch1.pack(side='left',padx=10,pady=10) var3=tk.IntVar() ch2=ttk.Checkbutton(fr2,text="多选按钮1",variable=var3) ch2.pack(side='left',padx=10,pady=10) sca1=tk.Scale(fr1,from_=0,to=255,orient=tk.HORIZONTAL) sca1.pack(side='left',padx=10,pady=10) sca2=ttk.Scale(fr2,from_=0,to=255,orient=tk.HORIZONTAL) sca2.pack(side='left',padx=10,pady=10) root.mainloop()
运行结果
由上可见,除了标签外,其它组件在风格上还是有明显的不同,ttk风格的确跟系统的主题更统一,看上去,也更舒服一些了。
在上面代码,对于标签 la2的创建是:
la2=ttk.Label(fr2,text='标签2',background='lightblue')
在tkinter的背景颜色设置上,用bg和用background都是可以的,但是,在ttk里是不支持bg,fg的,你可以把上面代码改成 bg='lightblue' 再去试一下,肯定出错。
那如何知道ttk组件支持什么参数,我们在创建la1,la2完以后,在代码加入
print(la1.keys()) print('----------------------') print(la2.keys())
运行后,会输出:
['activebackground', 'activeforeground', 'anchor', 'background', 'bd', 'bg', 'bitmap', 'borderwidth', 'compound', 'cursor', 'disabledforeground', 'fg', 'font', 'foreground', 'height', 'highlightbackground', 'highlightcolor', 'highlightthickness', 'image', 'justify', 'padx', 'pady', 'relief', 'state', 'takefocus', 'text', 'textvariable', 'underline', 'width', 'wraplength']
----------------------
['background', 'foreground', 'font', 'borderwidth', 'relief', 'anchor', 'justify', 'wraplength', 'takefocus', 'text', 'textvariable', 'underline', 'width', 'image', 'compound', 'padding', 'state', 'cursor', 'style', 'class']
由此可见,采取ttk模块的la2标签可采用的参数里,没有bg,只有background,但采用tkinter模块里就有bg这个参数。这方面的知识不用强记,多编程,多编码,自然就记住了。
style()方法,设置
我们知道ttk组件可以通过sytle对象来设置组件的外观等。现在我来用代码演示一下。
from tkinter import * from tkinter.ttk import * root=Tk() but1=Button(root,text="wb98.com",background='blue',foreground='red',font=('黑体',12,'bold')) but1.pack() root.mainloop()
以上代码想在窗体创建一个按钮,设置按钮的背景颜色为红色,前景颜色为红色,字体为黑体,但是,运行后,噫,出错了。
以上情况最常出现在新手刚从tkinter转到ttk来的时候,上面代码导入tkinter,ttk的通配符方式,决定ttk模块的组件会覆盖掉tkinter模块下的同名组件,所以,在上面代码应该按照ttk设置组件外观样式的方法,而不要沿用以前的方法 ,ttk模块设置方法是用style对象。下面我先来讲一下如何运用style对象及方法,其中ttk样式名的取名有规定,这个大家要强记一下。
Style对象创建方法: 对象名=Style()
例如:
style1=Style()
s2=Style()
wb98=Style()
Style对象设置方法:对象实例.configure('ttk样式名', 样式参数......)
例如:
style1.configure('TButton', background='blue',foreground='red')
s2.configure('my.TButton', background='blue',foreground='red')
wb98.configure('.', background='blue',foreground='red')
上面说的Style对象创建很简单,接着讲的configure设置方法也不难,关键是ttk样式名是有强制规定的:
如果你是为所有组件设置,系统已经强制ttk样式名为:'.'
例如:Style对象名. configure('.', background='blue',foreground='red')
设置成功后,窗体上的所有组件:按钮,标签,单选按钮……等都被设置成蓝色背景色,红色前景色。
如果你是为某类组件设置,系统也有强制ttk样式名:
大部分样式名都在组件类名的前面加大写的T
组件类 | ttk样式名 |
Button | TButton |
Checkbutton | TCheckbutton |
Radiobutton | TRadiobutton |
Entry | TEntry |
Combobox | TCombobox |
Frame | TFrame |
Label | TLabel |
LabelFrame | TLabelFrame |
Notebook | TNtebook |
Menubutton | TMenubutton |
PanedWindow | TPandwindow ( 不是TpandWindow ) |
Progressbar | Horizontal.TProgressbar Vertical.TProgressbar |
Scale | Horizontal.TScale Vertical.TScale |
Scrollbar | Horizontal.TScrollbar Vertical.TScrollbar |
Sizegrip | TSizegrip |
Separator | TSeparator |
Treeview | Treeview ( 不是 TTreeview ) |
例如:Style对象名. configure('TButton', background='blue',foreground='red')
设置成功后,窗体上所有的按钮都被设置成蓝色背景色,红色前景色,其它的组件,如标签,单选按钮等是不会接受影响的。
如果你只是为窗体上某一个单独的组件设置,其它同类的组件不受影响,你需要为这个单独设置的组件起一个样式名,样式名的格式是:自取的名字.组件类的强制名。
例如:我的一个按钮取样式名:my.TButton
我的一个标签取样式名:wb86.TLabel
下面结合上面讲解的知识,建立一个窗体,窗体上有3个组件,2个按钮,一个标签,我先为所有窗体上的组件进行设置,然后为窗体所有的按钮进行设置,再后,我只为其中的一个按钮进行设置。
先看看在ttk模块下,默认的样式是怎么样式吧:
from tkinter import * from tkinter.ttk import * root=Tk() but1=Button(root,text="我是按钮1") but1.pack(padx=60,pady=10) but2=Button(root,text="我是按钮2") but2.pack(padx=60,pady=10) la1=Label(root,text='我是标签') la1.pack(padx=60,pady=10) root.mainloop()
运行结果:
好了,大家记住上面的运行图,我先让所有的组件的样式都变一下,我在组件创建前加入style样式代码。
from tkinter import * from tkinter.ttk import * root=Tk() style1 = Style() # 创建Style对象,便于下面设置样式 style1.configure('.',background='blue',foreground='red',font=('黑体',12)) #设置背景颜色为蓝色,前景颜色为红色,'.'为所有组件的样式名 but1=Button(root,text="我是按钮1") but1.pack(padx=60,pady=10) but2=Button(root,text="我是按钮2") but2.pack(padx=60,pady=10) la1=Label(root,text='我是标签') la1.pack(padx=60,pady=10) root.mainloop()
运行结果
运行后,由于设置的样式名是:’.’ ,所以窗体上的三个组件,不管是按钮还是标签的外观样式都改变了。
好了,下面我们只改变按钮样式,不改变标签的样式:
from tkinter import * from tkinter.ttk import * root=Tk() style1 = Style() # 创建Style对象,便于下面设置样式 style1.configure('TButton',background='blue',foreground='red',font=('黑体',12)) #设置背景颜色为蓝色,前景颜色为红色,'TButton'为所有按钮组件的样式名 but1=Button(root,text="我是按钮1") but1.pack(padx=60,pady=10) but2=Button(root,text="我是按钮2") but2.pack(padx=60,pady=10) la1=Label(root,text='我是标签') la1.pack(padx=60,pady=10) root.mainloop()
运行结果
由于只设置了按钮的样式(’TButton’),所以只有2个按钮的外观样式有了变化,标签还是默认的样子。
下面,我进一步,只改变第1个按钮的样式,由于只是改变某个组件类的部分组件,这时,就需要为这个样式取一个自定义的名字:my.TButton
from tkinter import * from tkinter.ttk import * root=Tk() style1 = Style() # 创建Style对象,便于下面设置样式 style1.configure('my.TButton',background='blue',foreground='red',font=('黑体',12)) #设置背景颜色为蓝色,前景颜色为红色,'my.TButton'为部分按钮组件的样式名 but1=Button(root,text="我是按钮1",style='my.TButton') but1.pack(padx=60,pady=10) but2=Button(root,text="我是按钮2") but2.pack(padx=60,pady=10) la1=Label(root,text='我是标签') la1.pack(padx=60,pady=10) root.mainloop()
运行结果
测试成功,2个按钮中,只有按钮1样式有变化,另一个按钮是默认的样式,标签也是默认的样式。
请大家看清楚代码,一方面,Style对象设置时,在样式名是自定义 my.TButton ,另一方面,在要设置按钮的创建代码中,一定要加一个参数 style='my.TButton' ,这2地方的变动缺一不可,否则不能成功。
主题theme
各种风格统一的样式组件在一起,就组成了主题,ttk自带有几个主题,不同的电脑系统支持不同的主题,我们先来列出自己电脑系统支持的tkinter所有的主题。
from tkinter import * from tkinter.ttk import * root=Tk() style1 = Style() # 创建Style对象,便于下面设置样式 print(style1.theme_names()) # 输出本机ttk所有主题风格 print(style1.theme_use()) # 输出现在采用的那种主题 root.mainloop()
运行后,输入结果:(本人的电脑系统是window10)
('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
vista
可见,返回主题是一个所有主题的元组。
我的电脑采取的主题是 vista
用tkinter模块是不方便做程序的美化工作,导入ttk模块后,我们利用ttk模块支持的主题,做一个换肤程序就容易了。下面我们就来做一个换肤程序吧。
采取某款ttk主题的方法是: style1.theme_use('主题名')
在下面的代码里,tyle1.theme_names() 方法得到本题支持主题元组,作为optionmenu组件的列表项,供大家选择换主题。
from tkinter import * from tkinter.ttk import * root=Tk() # 源码来自wb98.com root.columnconfigure(0,weight=1,minsize=150) # 0列 限制最小宽度为150像素 root.columnconfigure(1,weight=1,minsize=150) # 1列 限制最小宽度为150像素 fr1=Frame(root) # fr1是作为窗体的底色而创建的 fr1.place(x=0,y=0,relwidth=1,relheight=1) # 参数保证fr1跟窗体一样大小 style1 = Style() # 创建Style对象,便于下面设置样式 tuple_op=style1.theme_names() # 返回值是本机ttk所有主题风格的元组 var=StringVar() def changejob(cs): # 参数正好就是选择项的文本 style1.theme_use(cs) op1=OptionMenu(root,var,*tuple_op,command=changejob) # 用下拉列表组件来选择主题 op1.grid() var.set(style1.theme_use()) # 组件默认选项设为目前的主题 lfr1=LabelFrame(root,text='单选') # 装入3个单选按钮 lfr1.grid(row=1,column=0,sticky='nswe',padx=10,pady=10) var1=IntVar() ra1=Radiobutton(lfr1,text='苹果',variable=var1,value=1).pack() ra1=Radiobutton(lfr1,text='西瓜',variable=var1,value=2).pack() ra1=Radiobutton(lfr1,text='葡萄',variable=var1,value=3).pack() var1.set(1) lfr2=LabelFrame(root,text='多选') # 装入3个多选按钮 lfr2.grid(row=1,column=1,sticky='nswe',padx=10,pady=10) var2,var3,var4=IntVar(),IntVar(),IntVar() ch1=Checkbutton(lfr2,text="足球",variable=var2).pack() ch2=Checkbutton(lfr2,text="田径",variable=var3).pack() ch3=Checkbutton(lfr2,text="游泳",variable=var4).pack() var3.set(True) var4.set(True) fr1=Frame(root) # 框架装入2个按钮 fr1.grid(row=2,column=0,columnspan=2,sticky=W+E,pady=(0,10)) but1=Button(fr1,text=" 退 出 ",command=root.destroy) but1.pack(side=RIGHT,padx=(10,30)) but2=Button(fr1,text=" 确 定 ") but2.pack(side=RIGHT) root.mainloop()
运行结果: 丶丌皛
上述都是用官方提供的主题包,加载速度不错,样式也还行。
我曾试过第三方的主题包,由于是以图片的形式来做主题包,加载速度在启动时,慢了好几秒,我放弃了,tkinter做为解释性语言本来就慢了,只是为了好看的界面而降低反映速度太多,本末倒置了。
此文章来自:wb98.com 网站还有相关的系列课程文章,感兴趣的可以前往。
下一篇文章,我来讲第一款TTK组件combobox
来源:济亨网
本文链接:http://wb98.com/post/335.html