在本文中,将介绍 Tkinter.ttk 主题小部件,是常规 Tkinter 小部件的升级版本。

Tkinter 有两种小部件:经典小部件、主题小部件。Tkinter 于 1991 年推出了经典小部件,2007 年在 Tk8.5 中添加新式的主题小部件。主题小部件更新了部分经典小部件,并增加了部分新的小部件。
要使用 tkinter.ttk 主题小部件,需要使用以下语句进行导入
import tkinter as tk
from tkinter import ttk
Tk 主题小部件改进了样式和主题,总共包含 18 种小部件 ,其中十二种已存在于 tkinter 中:
ButtonCheckbuttonEntryFrameLabelLabelFrameMenubuttonPanedWindowRadiobuttonScaleScrollbarSpinbox新增六种小部件:
ComboboxNotebookProgressbarSeparatorSizegripTreeviewTkinter 小部件具有更基本和传统的外观,而 Ttk 小部件提供更现代的外观,可以更好地适应各种新的操作系统。
ttk 提供了增强的主题选项,允许开发人员使用各种预定义的样式和主题。提升了性能,提供了更好的用户体验。
Tkinter 小部件更适合初学者使用,Ttk 小部件引入了更多的复杂特性,在处理样式和主题时,提供了更大的灵活性。
Tkinter 小部件与Tkinter.Ttk 小部件的主要区别:
特征
Tkinter 小部件
Tkinter.Ttk 小部件
外观
传统的外观
现代主题外观
主题
有限的主题功能
具有各种预定义样式的增强主题
跨平台
在所有操作系统上外观基本保持一致
适应不同的操作系统
定制
小部件特定的选项
基于样式的自定义
性能
适用简单的应用程序
适合更复杂的应用程序
复杂性
初学者容易使用
略微复杂
Tkinter 小部件与 Ttk 小部件 基本外观对比
import tkinter as tkfrom tkinter import ttkroot = tk.Tk()root.geometry('600x400+200+200')root.title('Ttk 主题小部件演示')left_frame = tk.Frame(root, width=300, height=400)left_frame.pack(side='left', fill='both', padx=10, pady=5, expand=True)right_frame = tk.Frame(root, width=300, height=400)right_frame.pack(side='right', fill='both', padx=10, pady=5, expand=True)def callback(): passlabel = tk.Label(left_frame, text='标签')label.pack(pady=5)label = ttk.Label(right_frame, text='ttk标签')label.pack(pady=5)button = tk.Button(left_frame, text="按钮", command=callback)button.pack(pady=5)button = ttk.Button(right_frame, text="ttk按钮", command=callback)button.pack(pady=5)entry1 = tk.Entry(left_frame)entry1.pack(pady=5)entry1.insert(0, "单行文本框")entry2 = ttk.Entry(right_frame)entry2.pack(pady=5)entry2.insert(0, "ttk单行文本框")frame1 = tk.LabelFrame(left_frame, text='复选框')frame1.pack(pady=5)cb1 = tk.Checkbutton(frame1, text='Number 1')cb1.pack()cb2 = tk.Checkbutton(frame1, text='Number 2')import tkinter as tkfrom tkinter import ttkroot = tk.Tk()root.geometry('600x400+200+200')root.title('Ttk 主题小部件演示')style=ttk.Style()style.theme_use('classic')style.configure("design.TLabel",background="green",foreground="white",font="Arial 16 bold", padding=20)style.configure("design.TButton",background="red",foreground="white",font="Arial 16 bold", padding=20)label=ttk.Label(root,text = f"Ttk 标签", style = "design.TLabel")label.pack(pady=10)button=ttk.Button(root,text = "Ttk 按钮", style = "design.TButton")button.pack(pady=10)root.mainloop()cb2.pack()frame2 = ttk.LabelFrame(right_frame, text='ttk复选框')frame2.pack(pady=5)cb3 = ttk.Checkbutton(frame2, text='Number 3')cb3.pack()cb4 = ttk.Checkbutton(frame2, text='Number 4')cb4.pack()frame3 = tk.LabelFrame(left_frame, text='单选按钮')frame3.pack(pady=5)r1 = tk.Radiobutton(frame3,text="option 1", value=1)r1.pack()r2 = tk.Radiobutton(frame3,text="option 2", value=2)r2.pack()frame4 = ttk.LabelFrame(right_frame, text='ttk单选按钮')frame4.pack(pady=5)r1 = ttk.Radiobutton(frame4,text="option 1", value=1)r1.pack()r2 = ttk.Radiobutton(frame4,text="option 2", value=2)r2.pack()scale1 = tk.Scale(left_frame, from_=0, to=100, orient='horizontal', length=100)scale1.pack(pady=5)scale2 = ttk.Scale(right_frame, from_=0, to=100, orient='horizontal', length=100)scale2.pack(pady=5)menubttn = tk.Menubutton(left_frame, text = "菜单按钮", relief = tk.RAISED)menu = tk.Menu(menubttn, tearoff = 0)menu.add_checkbutton(label = "Python")menu.add_checkbutton(label = "Java")menubttn["menu"] = menumenubttn.pack(pady=5)menubttn = ttk.Menubutton(right_frame, text = "ttk菜单按钮")menu = tk.Menu(menubttn, tearoff = 0)menu.add_checkbutton(label = "Python")menu.add_checkbutton(label = "Java")menubttn["menu"] = menumenubttn.pack(pady=5)spinbox1 = tk.Spinbox(left_frame, from_=0, to=10, wrap=True)spinbox1.pack()spinbox2 = ttk.Spinbox(right_frame, from_=0, to=10, wrap=True)spinbox2.pack()root.mainloop()
Ttk 可以使用 theme_names() 方法,获取所有可用主题的列表。使用 theme_use() 方法,应用主题。
import tkinter as tkfrom tkinter import ttkroot = tk.Tk()root.geometry('600x400+200+200')root.title('Ttk 主题小部件演示')text = tk.StringVar()style = ttk.Style(root)def change_theme(): style.theme_use(selected_theme.get()) def callback(): passleft_frame = tk.Frame(root, width=300, height=400)left_frame.pack(side='left', fill='both', padx=10, pady=5, expand=True)right_frame = tk.Frame(root, width=300, height=400)right_frame.pack(side='right', fill='both', padx=10, pady=5, expand=True)selected_theme = tk.StringVar()theme_frame = ttk.LabelFrame(left_frame, text='Themes')theme_frame.pack(padx=10, pady=10, ipadx=20, ipady=20)for theme_name in style.theme_names(): rb = ttk.Radiobutton( theme_frame, text=theme_name, value=theme_name, variable=selected_theme, command=change_theme) rb.pack(expand=True, fill='both')label = ttk.Label(right_frame, text='ttk标签')label.pack(pady=5)button = ttk.Button(right_frame, text="ttk按钮", command=callback)button.pack(pady=5)entry = ttk.Entry(right_frame, textvariable=text, text="文本框")entry.pack(pady=5)entry.insert(0, "ttk单行文本框")frame2 = ttk.LabelFrame(right_frame, text='ttk复选框')frame2.pack(pady=5)cb3 = ttk.Checkbutton(frame2, text='Number 3')cb3.pack()cb4 = ttk.Checkbutton(frame2, text='Number 4')cb4.pack()frame4 = ttk.LabelFrame(right_frame, text='ttk单选按钮')frame4.pack(pady=5)r1 = ttk.Radiobutton(frame4,text="option 1", value=1)r1.pack()r2 = ttk.Radiobutton(frame4,text="option 2", value=2)r2.pack()scale2 = ttk.Scale(right_frame, from_=0, to=100, orient='horizontal', length=100)scale2.pack(pady=5)menubttn = ttk.Menubutton(right_frame, text = "ttk菜单按钮")menu = tk.Menu(menubttn, tearoff = 0)menu.add_checkbutton(label = "Python")menu.add_checkbutton(label = "Java")menubttn["menu"] = menumenubttn.pack(pady=5)spinbox2 = ttk.Spinbox(right_frame, from_=0, to=10, wrap=True)spinbox2.pack(pady=5)root.mainloop()
Ttk 中的每个小部件都有一个默认样式,该样式包含了一些自定义设置。
小部件
样式名称
Button
TButton
Checkbutton
TCheckbutton
Combobox
TCombobox
Entry
TEntry
Frame
TFrame
Label
TLabel
LabelFrame
TLabelFrame
Menubutton
TMenubutton
Notebook
TNotebook
PanedWindow
TPanedwindow
Progressbar
Horizontal.TProgressbar / Vertical.TProgressbar
Radiobutton
TRadiobutton
Scale
Horizontal.TScale / Vertical.TScale
Scrollbar
Horizontal.TScrollbar / Vertical.TScrollbar
Separator
TSeparator
Sizegrip
TSizegrip
Treeview
Treeview
每个样式都有一组定义小部件外观的选项。要修改样式,请使用以下方法:
style = ttk.Style()
style.configure(style_name, **options)
import tkinter as tkfrom tkinter import ttkroot = tk.Tk()root.geometry('600x400+200+200')root.title('Ttk 主题小部件演示')style=ttk.Style()style.theme_use('classic')style.configure("design.TLabel",background="green",foreground="white",font="Arial 16 bold", padding=20)style.configure("design.TButton",background="red",foreground="white",font="Arial 16 bold", padding=20)label=ttk.Label(root,text = f"Ttk 标签", style = "design.TLabel")label.pack(pady=10)button=ttk.Button(root,text = "Ttk 按钮", style = "design.TButton")button.pack(pady=10)root.mainloop()
使用 Ttk 样式的 map() 方法根据特定事件动态更改小组件的外观。
import tkinter as tkfrom tkinter import ttkroot = tk.Tk()root.geometry('600x400+200+200')root.title('Ttk 主题小部件演示')style = ttk.Style()style.configure('TButton', font=('Helvetica', 16))style.map('TButton', foreground=[('pressed', 'blue'), ('active', 'red')])button = ttk.Button(root, text='按钮')button.pack(pady=20)button = ttk.Button(root, text='按钮')button.pack(pady=20)root.mainloop()
在以上示例中,当将鼠标移动到按钮上时,其文本颜色将变为红色。当单击或按下按钮时,其文本颜色将变为蓝色。