Python 提供了多种用于开发图形用户界面(GUI)的选择。最重要的特性如下所示。
Tkinter
Tkinter 是 Python 对附带在 Python 中的 Tk GUI 工具包的接口。本章将探讨这个选项。
wxPython
这是一个开放源码的 Python 接口,用于 wxWidgets GUI 工具包。你可以在这里找到完整的 wxPython 教程。
PyQt
这也是一个 Python 接口,用于流行的跨平台 Qt GUI 库。TutorialsPoint 上有一篇关于 PyQt5 非常好的教程。
PyGTK
PyGTK 是一组用 Python 和 C 编写的 GTK+ GUI 库的包装器。完整的 PyGTK 教程可在这里找到。
PySimpleGUI
PySimpleGUI 是一个开源的、跨平台的 Python GUI 库。它的目标是基于 Python 的 Tkinter、PySide 和 WxPython 工具包提供一个统一的 API 用于创建桌面 GUI。详细的 PySimpleGUI 教程可点击这里。
Pygame
Pygame 是一个用于开发视频游戏的流行 Python 库。它是免费、开源的,并且是一个跨平台的围绕 Simple DirectMedia Layer (SDL) 的包装器。一份全面的 Pygame 教程可以在这里找到。
Jython
Jython 是 Python 在 Java 平台上的移植版,可以让 Python 脚本无缝访问本地机器上的 Java 类库。
还有很多其他的接口,你可以在网上找到它们。
Tkinter 编程
Tkinter 是 Python 的标准 GUI 库。当 Python 结合 Tkinter 时,它可以快速而容易地创建 GUI 应用程序。Tkinter 为 Tk GUI 工具包提供了一个强大的面向对象接口。
tkinter
包含了以下模块:
-
-
tkinter.colorchooser - 允许用户选择颜色的对话框。
-
tkinter.commondialog - 在此列出的其他模块中定义的对话框的基础类。
-
tkinter.filedialog - 常见的对话框,允许用户指定要打开或保存的文件。
-
tkinter.font - 帮助处理字体的工具。
-
tkinter.messagebox - 访问标准的 Tk 对话框。
-
tkinter.scrolledtext - 内置垂直滚动条的文字控件。
-
tkinter.simpledialog - 基础对话框和便利函数。
-
tkinter.ttk - 在 Tk 8.5 中引入的主题化控件集,为主 Tkinter 模块中的许多经典控件提供了现代替代方案。
使用 Tkinter 创建 GUI 应用程序是一件简单的事情。你需要做的就是执行以下步骤:
-
-
-
-
进入主事件循环,以便对用户触发的每个事件采取行动。
示例
注意模块名在 Python 2 中为 Tkinter,在 Python 3 中改为 tkinter
import tkinter
top = tkinter.Tk()
top.mainloop()
这会创建一个如下所示的窗口:
当程序变得更加复杂时,采用面向对象的编程方法可以使代码更加有组织。
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
app = App()
app.mainloop()
Tkinter 控件
Tkinter 提供了各种控件,如按钮、标签和文本框等,这些控件通常用于 GUI 应用程序中。这些控件通常被称为小部件。
目前 Tkinter 中有 15 种类型的小部件。我们在下表中列出了这些小部件以及简短的描述:
序号 |
控件 |
描述 |
1 |
Button |
Button 控件用于显示应用程序中的按钮。 |
2 |
Canvas |
Canvas 控件用于在应用程序中绘制线条、椭圆、多边形和矩形等形状。 |
3 |
Checkbutton |
Checkbutton 控件用于以复选框的形式显示多个选项。用户可以同时选择多个选项。 |
4 |
Entry |
Entry 控件用于显示单行文本字段以接受用户的输入。 |
5 |
Frame |
Frame 控件用作容器控件来组织其他控件。 |
6 |
Label |
Label 控件用于为其他控件提供单行标题。它也可以包含图像。 |
7 |
Listbox |
Listbox 控件用于向用户提供一个选项列表。 |
8 |
Menubutton |
Menubutton 控件用于在应用程序中显示菜单。 |
9 |
Menu |
Menu 控件用于向用户提供各种命令。这些命令包含在 Menubutton 中。 |
10 |
Message |
Message 控件用于显示多行文本字段以接受用户的输入。 |
11 |
Radiobutton |
Radiobutton 控件用于以单选按钮的形式显示多个选项。用户一次只能选择一个选项。 |
12 |
Scale |
Scale 控件用于提供滑块控件。 |
13 |
Scrollbar |
Scrollbar 控件用于为诸如列表框等各种控件添加滚动功能。 |
14 |
Text |
Text 控件用于显示多行文本。 |
15 |
Toplevel |
Toplevel 控件用于提供一个单独的窗口容器。 |
16 |
Spinbox |
Spinbox 控件是标准 Tkinter Entry 控件的一个变体,可以用来从一组固定数值中选择。 |
17 |
PanedWindow |
PanedWindow 是一个可以水平或垂直排列任意数量窗格的容器控件。 |
18 |
LabelFrame |
LabelFrame 是一个简单的容器控件。其主要目的是作为间隔或用于复杂的窗口布局的容器。 |
19 |
tkMessageBox |
该模块用于在应用程序中显示消息框。 |
让我们详细了解这些控件。
标准属性
让我们来看看一些常见的属性,例如大小、颜色和字体是如何规定的。
让我们简要地研究一下它们:
几何管理
所有的 Tkinter 小部件都可以访问特定的几何管理方法,这些方法的目的在于在整个父小部件区域内组织小部件。Tkinter 提供了以下几何管理器类:pack、grid 和 place。
pack() 方法
这种几何管理器将小部件组织成块,然后再放置在父小部件中。
grid() 方法
这种几何管理器将小部件以表格形式组织在父小部件中。
place() 方法
这种几何管理器通过将小部件放置在父小部件中的特定位置来组织小部件。
让我们简要地研究一下几何管理方法:
SimpleDialog
tkinter 包中的 simpledialog 模块包括一个对话框类和用于通过模式对话框接收用户输入的便利函数。它包含一个标签、一个输入框和两个按钮 Ok 和 Cancel。这些函数是:
-
askfloat(title, prompt, **kw)
— 接受一个浮点数。
-
askinteger(title, prompt, **kw)
— 接受一个整数输入。
-
askstring(title, prompt, **kw)
— 接受用户输入的文本。
以上三个函数提供了提示用户输入所需类型值的对话框。如果按下 Ok,则返回输入;如果按下 Cancel,则返回 None。
askinteger 示例
from tkinter.simpledialog import askinteger
from tkinter import *
from tkinter import messagebox
top = Tk()
top.geometry("100x100")
def show():
num = askinteger("Input", "Input an Integer")
print(num)
B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)
top.mainloop()
它将产生以下输出:
askfloat 示例
from tkinter.simpledialog import askfloat
from tkinter import *
top = Tk()
top.geometry("100x100")
def show():
num = askfloat("Input", "Input a floating point number")
print(num)
B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)
top.mainloop()
它将产生以下输出:
askstring 示例
from tkinter.simpledialog import askstring
from tkinter import *
top = Tk()
top.geometry("100x100")
def show():
name = askstring("Input", "Enter your name")
print(name)
B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)
top.mainloop()
它将产生以下输出:
文件对话框模块
Tkinter 包中的 filedialog 模块包括一个 FileDialog 类。它还定义了方便用户执行打开文件、保存文件和打开目录活动的函数。
-
filedialog.asksaveasfilename()
-
filedialog.asksaveasfile()
-
filedialog.askopenfilename()
-
-
filedialog.askdirectory()
-
filedialog.askopenfilenames()
-
filedialog.askopenfiles()
askopenfile 示例
这个函数让用户从文件系统中选择一个想要的文件。文件对话框窗口有 Open 和 Cancel 按钮。当按下 Ok 时返回文件名及其路径,如果按下 Cancel 则返回 None。
from tkinter.filedialog import askopenfile
from tkinter import *
top = Tk()
top.geometry("100x100")
def show():
filename = askopenfile()
print(filename)
B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)
top.mainloop()
它将产生以下输出:
ColorChooser
tkinter 包中包含的 colorchooser 模块具有通过颜色对话框让用户选择所需颜色的功能。askcolor()
函数提供了预定义的颜色样本以及通过设置 RGB 值来选择自定义颜色的设施。对话框返回所选颜色的 RGB 值元组及其十六进制值。
from tkinter.colorchooser import askcolor
from tkinter import *
top = Tk()
top.geometry("100x100")
def show():
color = askcolor()
print(color)
B = Button(top, text ="Click", command = show)
B.place(x=50,y=50)
top.mainloop()
它将产生以下输出:
((0, 255, 0), '#00ff00')
ttk 模块
术语 ttk 代表带有主题的 Tk 小部件。ttk 模块自 Tk 8.5 开始引入。它提供了额外的好处,包括在 X11 下的抗锯齿字体渲染和窗口透明性。它为 Tkinter 提供了主题和样式支持。
ttk 模块捆绑了 18 个小部件,其中 12 个已经在 Tkinter 中存在。导入 ttk 会覆盖这些小部件,这些新小部件设计为在所有平台上都有更好的、更现代化的外观。
ttk 中的六个新小部件是 Combobox、Separator、Sizegrip、Treeview、Notebook 和 ProgressBar。
为了覆盖基本的 Tk 小部件,导入应该遵循 Tk 导入:
from tkinter import *
from tkinter.ttk import *
原始的 Tk 小部件会被 tkinter.ttk 小部件自动替换。这些小部件包括 Button、Checkbutton、Entry、Frame、Label、LabelFrame、Menubutton、PanedWindow、Radiobutton、Scale 和 Scrollbar。
新小部件在各个平台上提供了更好的外观和感觉;然而,替换的小部件并不完全兼容。主要的区别在于像 "fg"、"bg" 以及其他与小部件样式相关的选项不再存在于 ttk 小部件中。相反,请使用 ttk.Style 类以获得改进的样式效果。
ttk 模块中的新小部件包括:
-
Notebook - 此小部件管理一系列可以切换的“选项卡”,更改当前显示的窗口。
-
ProgressBar - 此小部件用于通过动画显示进度或加载过程。
-
Separator - 用于使用分割线分离不同的小部件。
-
Treeview - 此小部件用于将项分组在一个类似树的层次结构中。每个项都有一个文本标签、一个可选的图像和一个可选的数据值列表。
-
ComboBox - 用于创建一个下拉列表,用户可以从其中选择一个选项。
-
Sizegrip - 在屏幕右下角创建一个小把手,可以用来调整窗口大小。
Combobox 小部件
Python ttk Combobox 提供了一个下拉列表的选项,并一次显示一个。它是 Entry 小部件的子类,因此继承了许多来自 Entry 类的方法和选项。
语法
from tkinter import ttk
Combo = ttk.Combobox(master, values=...)
使用 get()
函数来检索 Combobox 的当前值。
示例
from tkinter import *
from tkinter import ttk
top = Tk()
top.geometry("200x150")
frame = Frame(top)
frame.pack()
langs = ["C", "C++", "Java", "Python", "PHP"]
Combo = ttk.Combobox(frame, values = langs)
Combo.set("Pick an Option")
Combo.pack(padx = 5, pady = 5)
top.mainloop()
它将产生以下输出:
Progressbar
ttk ProgressBar 小部件,以及如何使用它创建加载屏幕或显示当前任务的进度。
语法
ttk.Progressbar(parent, orient, length, mode)
参数
-
Parent - ProgressBar 所放置的容器,比如 root 或者 Tkinter frame。
-
Orient - 定义 ProgressBar 的方向,可以是垂直或水平。
-
Length - 定义 ProgressBar 的宽度,需要一个整数值。
-
Mode - 有两个选项,determinate 和 indeterminate。
示例
下面的代码创建了一个带有三个按钮的 progressbar,这三个按钮分别链接到三个不同的函数。
第一个函数通过 step()
函数增加 progressbar 的 “value” 或 “progress”,默认增量是 1.0。
第二个函数减少 progressbar 的 “value” 或 “progress”。
第三个函数打印出 progressbar 的当前进度级别。
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
frame = ttk.Frame(root)
def increment():
progressBar.step(20)
def decrement():
progressBar.step(-20)
def display():
print(progressBar["value"])
progressBar = ttk.Progressbar(frame, mode='determinate')
progressBar.pack(padx = 10, pady = 10)
button = ttk.Button(frame, text= "Increase", command= increment)
button.pack(padx = 10, pady = 10, side = tk.LEFT)
button = ttk.Button(frame, text= "Decrease", command= decrement)
button.pack(padx = 10, pady = 10, side = tk.LEFT)
button = ttk.Button(frame, text= "Display", command= display)
button.pack(padx = 10, pady = 10, side = tk.LEFT)
frame.pack(padx = 5, pady = 5)
root.mainloop()
它将产生以下输出:
Notebook
Tkinter ttk 模块有一个新的有用的叫做 Notebook 的小部件。这是一个由容器(如 frames)组成的集合,里面有许多作为子元素的小部件。
每个“选项卡”或“窗口”都有一个与之关联的选项卡 ID,用于确定切换到哪个选项卡。
你可以像在常规文本编辑器中一样在这些建容器之间切换。
语法
notebook = ttk.Notebook(master, *options)
示例
在这个示例中,以两种不同的方式向 Notebook 小部件添加 3 个窗口。第一种方法涉及 add()
函数,它只是将一个新的选项卡追加到最后。另一种方法是 insert()
函数,它可以用来在特定位置添加一个选项卡。
add()
函数需要一个必须的参数,即要添加的容器小部件,其余的是可选参数,如 text(作为选项卡标题显示的文本)、image 和 compound。
insert()
函数需要一个 tab_id
,用于定义插入的位置。tab_id
可以是一个索引值,也可以是一个字符串字面量如 "end",它将把选项卡追加到最后。
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
nb = ttk.Notebook(root)
frame1 = ttk.Frame(nb)
frame2 = ttk.Frame(nb)
label1 = ttk.Label(frame1, text = "这是窗口一")
label1.pack(pady = 50, padx = 20)
label2 = ttk.Label(frame2, text = "这是窗口二")
label2.pack(pady = 50, padx = 20)
frame1.pack(fill= tk.BOTH, expand=True)
frame2.pack(fill= tk.BOTH, expand=True)
nb.add(frame1, text = "窗口 1")
nb.add(frame2, text = "窗口 2")
frame3 = ttk.Frame(nb)
label3 = ttk.Label(frame3, text = "这是窗口三")
label3.pack(pady = 50, padx = 20)
frame3.pack(fill= tk.BOTH, expand=True)
nb.insert("end", frame3, text = "窗口 3")
nb.pack(padx = 5, pady = 5, expand = True)
root.mainloop()
它将产生以下输出:
Treeview
Treeview 小部件用于以表格或层次结构的方式显示项目。它支持创建项目行和列的功能,同时也允许项目拥有子项目,从而形成层次结构。
语法
tree = ttk.Treeview(container, **options)
选项
序号 |
选项 |
描述 |
1 |
columns |
列名列表 |
2 |
displaycolumns |
列标识符列表(符号或整数索引),指定哪些数据列显示及其顺序,或者字符串 "#all"。 |
3 |
height |
显示的行数。 |
4 |
padding |
规定小部件的内部填充。可以是一个整数或一个包含 4 个值的列表。 |
5 |
selectmode |
"extended"、"browse" 或 "none" 中的一个。如果设置为 "extended"(默认),可以选择多个项。如果 "browse",一次只能选择一个项。如果 "none",用户无法改变选择。 |
6 |
show |
包含零个或多个以下值的列表,指定显示树的哪些元素,默认是 "tree headings",即显示所有元素。 |
示例
在这个示例中,我们将创建一个简单的 Treeview ttk 小部件并在其中填充一些数据。我们已经有一些存储在列表中的数据,这些数据将在我们的 read_data()
函数中读取并添加到 Treeview 小部件中。
我们首先需要定义一个列名称的列表/元组。我们省略了列 "Name",因为已经存在一个名为空白的默认列。
然后我们将这个列表/元组赋给 Treeview 的 columns
选项,接着定义 "headings",其中 column
是实际的列,而 heading
仅仅是当小部件显示时出现的列的标题。我们给每一列命名,"#0" 是默认列的名字。
tree.insert()
函数有如下参数:
-
-
Position - 我们希望添加新项的位置。为了追加,使用
tk.END
。
-
-
Text - 我们将分配列表中的第一个值(名字)。
-
Values - 我们将传递从列表中获取的其他2个值。
完整的代码
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import simpledialog
root = tk.Tk()
data = [
["Bobby",26,20000],
["Harrish",31,23000],
["Jaya",18,19000],
["Mark",22, 20500],
]
def read_data():
for index, line in enumerate(data):
tree.insert('', tk.END, iid = index,
text = line[0], values = line[1:])
columns = ("age", "salary")
tree = ttk.Treeview(root, columns=columns ,height = 20)
tree.pack(padx = 5, pady = 5)
tree.heading('#0', text='Name')
tree.heading('age', text='Age')
tree.heading('salary', text='Salary')
read_data()
root.mainloop()
它将产生以下输出:
Sizegrip
Sizegrip 小部件基本上是一个位于屏幕右下角的小箭头形把手。拖动 Sizegrip 也会调整其附着的容器的大小。
语法
sizegrip = ttk.Sizegrip(parent, **options)
示例
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
root.geometry("100x100")
frame = ttk.Frame(root)
label = ttk.Label(root, text = "你好,世界")
label.pack(padx = 5, pady = 5)
sizegrip = ttk.Sizegrip(frame)
sizegrip.pack(expand = True, fill = tk.BOTH, anchor = tk.SE)
frame.pack(padx = 10, pady = 10, expand = True, fill = tk.BOTH)
root.mainloop()
它将产生以下输出:
Separator
ttk 分隔符小部件是一个非常简单的小部件,其唯一目的是通过在它们之间绘制一条线来帮助“分隔”小部件成组/分区。我们可以改变这条线(分隔符)的方向为水平或垂直,并改变它的长度/高度。
语法
separator = ttk.Separator(parent, **options)
参数
-
orient - 可以是
tk.VERTICAL
或 tk.HORIZONTAL
,分别用于垂直和水平分隔符。
示例
这里我们创建了两个 Label 小部件,然后在它们之间创建了一个水平分隔符。
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
root.geometry("200x150")
frame = ttk.Frame(root)
label = ttk.Label(frame, text = "你好,世界")
label.pack(padx = 5)
separator = ttk.Separator(frame, orient= tk.HORIZONTAL)
separator.pack(expand = True, fill = tk.X)
label = ttk.Label(frame, text = "欢迎来到 TutorialsPoint")
label.pack(padx = 5)
frame.pack(padx = 10, pady = 50, expand = True, fill = tk.BOTH)
root.mainloop()
它将产生以下输出: