Python中的Tkinter图形用户界面设计(第1节)


初学者对于“图形用户界面”这个名词一定会很迷茫,其实在我们的日常工作与学习中,我们经常用到“图形用户界面”。比如,当我们打开QQ或者微信软件后,在电脑桌面上会弹出QQ或者微信的登录界面,成功登录后会显示个人的用户主界面,这些都可以被称作“图形用户界面”,它的任务就是完成程序软件与用户的交互。

1、图形用户界面(GUI)的定义

图形用户界面(英文Graphical User Interface,简称GUI),又称图形用户接口。它是一种计算机操作界面,通过图形方式显示应用程序的操作界面,用户可以通过鼠标、键盘等输入设备进行操作。GUI的出现极大地简化了用户与计算机之间的交互,使得用户可以通过直观的图形界面进行操作,而不需要记住复杂的命令和语法。GUI通常包括窗口、菜单、按钮、图标等元素,用户可以通过这些元素来执行各种操作,例如打开文件、编辑文本、浏览网页或执行其它一些日常任务。GUI的设计需要考虑用户友好性、易用性和美观性,以便让用户更加方便地使用计算机。在现代计算机系统中,GUI已经成为主流的用户界面形式,几乎所有的操作系统和应用程序都采用了GUI来提供用户操作界面。总的来说,GUI在计算机术语中指的是图形用户界面,是一种通过图形方式进行交互的用户界面形式。

Python作为一种强大而多功能的编程语言,广泛运用于Web网站开发、应用程序开发、数据分析、人工智能等领域。在大多数的应用程序中,图形用户界面(GUI)是程序与用户进行交互的主要方式。因此,学习如何创建GUI应用程序对于Python开发人员来说至关重要。

2、常用的GUI库

Python提供了多个GUI库可供选择,用于开发和设计图形用户界面程序,如Tkinter、PyQt、wxPython等。

Tkinter是Python的标准GUI库,支持跨平台的GUI程序开发,它提供了创建窗口、按钮、文本框和其他GUI组件的工具。它是一个轻量级的库,简单易用,适合小型的GUI程序开发,也特别适合初学者学习GUI图形用户界面编程。

PyQt是一个用于创建桌面应用程序的库,它使用Qt库(一个跨平台的C++库)的Python绑定。PyQt提供了许多GUI组件,包括窗口、按钮、文本框、菜单等,以及一些常用的工具,如数据库连接和网络编程,适合大型GUI程序开发。

wxPython是另一个用于创建桌面应用程序的Python库,它使用wxWidgets库(一个跨平台的C++库)的Python绑定。wxPython提供了许多GUI组件,以及一些常用的工具,如文件和目录操作、网络编程等。

本节教程我们将详细讲解Tkinter库,因为它是Python标准库的一部分,具有广泛的支持和运用,是入门GUI图形用户界面编程的理想选择。

3、Tkinter用法详解

在Python中可以通过图形用户界面(GUI)来进行图形页面应用程序的开发,Tkinter库是Python的默认GUI库,是一个内置模块,可以说是Python的标准GUI库,因此无需进行任何安装。与其它GUI相比,它操作简单、可移植性(可以在大多数的操作系统上运行,包括Windows、Mac和Linux等),可以通过“import thinter”或“from tkinter import *”语句导入该模块。

(1)创建基本窗口

使用Python的Tkinter库,我们可以轻松地创建一个简单的GUI应用程序。每个GUI应用程序至少应该创建一个窗口,称为主窗口,它作为用户与应用程序间的主界面来提供服务。主窗口是一切控件的基础,所有的控件的都需要通过主窗口来显示。下面我们通过Tkinter创建一个基本的窗口:

动手练一练:

# 导入tkinter模块,用于创建GUI应用程序
import tkinter as tk

# 创建一个主窗口对象
app = tk.Tk()
# 设置窗口标题,也就是窗口的名字
app.title('弹出窗口示例')
# 设置窗口大小,这里的乘号不是“*”,而是小写英文字母“x”
app.geometry('300x200')
# 创建标签控件
label = tk.Label(app, text='这是我的第一个tkinter程序')
# 将标签控件添加到窗口中
label.pack()
# 开启主循环,让窗口处于显示状态
app.mainloop()

执行以上代码,运行结果如下图:

可以看出运行结果会弹出一个简单的窗口,其中包含“这是我的第一个tkinter程序”的标签。Tkinter创建一个主窗口主要包括以下四个步骤:

(第一步)导入Tkinter模块:在代码开头添加“import tkinter as tk”,这将导入Tkinter模块并为其指定一个别名“tk”。

(第二步)创建主窗口:使用“app = tk.Tk()”创建一个名为“app”的主窗口对象,我们通过“app”主窗口对象设置了窗口的标题和大小,注意这里设置的大小“300x200”代表“宽x高”,默认是以像素(px)为单位,并且中间的乘号不是“*”,而是小写英文字母“x”。这里,我们可以借助鼠标拖动窗口和改变窗口大小,也可以把它关闭、最小化、最大化。

(第三步)添加标签控件:使用“tk.Label(app, text='这是我的第一个tkinter程序')”在窗口中添加一个标签。这将创建一个标签控件,标签的文本设置为“这是我的第一个tkinter程序”,并使用pack()方法将标签添加到窗口中。

(第四步)一直显示窗口:使用“app.mainloop()”显示窗口,并进入GUI事件主循环中,除非用户关闭,否则程序始终处于运行状态。

下表列出了窗口的常用方法:

函数 说明
title("标题") 接受一个字符串参数,为窗口起一个标题
resizable() 是否允许用户拉伸主窗口大小,默认为可更改,当设置为 resizable(0,0)或者resizable(False,False)时不可更改
geometry() 设定主窗口的大小以及位置,当参数值为None时表示获取窗口的大小和位置信息。
quit() 关闭当前窗口
update() 刷新当前窗口
mainloop() 设置窗口主循环,使窗口循环显示(一直显示,直到窗口被关闭)
iconbitmap() 设置窗口左上角的图标(注意图标必须是.ico文件类型)
config(background ="red") 设置窗口的背景色为红色,也可以接受16进制的颜色值
minsize(50,50) 设置窗口被允许调整的最小范围,即宽和高各50
maxsize(400,400) 设置窗口被允许调整的最大范围,即宽和高各400
attributes("-alpha",0.5) 用来设置窗口的一些属性,比如透明度(-alpha)、是否置顶(-topmost)即将主屏置于其他图标之上、是否全屏(-fullscreen)全屏显示等
state("normal") 用来设置窗口的显示状态,参数值normal(正常显示),icon(最小化),zoomed(最大化),
withdraw() 用来隐藏主窗口,但不会销毁窗口。
iconify() 设置窗口最小化
deiconify() 将窗口从隐藏状态还原
winfo_screenwidth(),winfo_screenheight() 获取电脑屏幕的分辨率(尺寸)
winfo_width(),winfo_height() 获取窗口的大小,同样也适用于其他控件,但是使用前需要使用update()刷新屏幕,否则返回值为1
protocol("协议名",回调函数) 启用协议处理机制,常用协议有WN_DELETE_WINDOW,当用户点击关闭窗口时,窗口不会关闭,而是触发回调函数。

下面演示Tkinter中窗口的常用方法,例如:

动手练一练:

# 导入tkinter模块,用于创建GUI应用程序
import tkinter as tk

# 创建一个主窗口对象
app =tk.Tk()
# 设置窗口标题,也就是窗口的名字
app.title("窗口的常用方法示例")
# 设置窗口大小:宽x高,并指定窗口在屏幕上的位置为(200, 200)
# 这里的乘号不是“*”,而是小写英文字母“x”
app.geometry("450x300+200+200")
# 获取电脑屏幕的大小
print("电脑的分辨率是%dx%d"%(app.winfo_screenwidth(),app.winfo_screenheight()))
# 要求窗口的大小,必须先刷新一下屏幕
app.update()
print("窗口的分辨率是%dx%d"%(app.winfo_width(),app.winfo_height()))
# 如使用该函数则窗口不能被拉伸
# app.resizable(False,False)
# 改变背景颜色为粉红色
app.config(background="pink")
# 设置窗口处于顶层
app.attributes("-topmost",True)
# 设置窗口的透明度
app.attributes("-alpha",1)
# 设置窗口被允许最大调整的范围,与resizble()冲突
app.maxsize(600,600)
# 设置窗口被允许最小调整的范围,与resizble()冲突
app.minsize(50,50)
# 更改左上角窗口的icon图标,加载logo图标
# 如果没有.ico图标文件类型,可以使用在线图标制作工具将png、jpeg等格式的图片转换为ico格式
# app.iconbitmap("favicon.ico")
# 添加标签控件,并对标签的字体添加相应的格式font(字体,字号,"字体类型")
text=tk.Label(app,text="这是一个简单的窗口示例",bg="yellow",fg="red",font=("黑体", 15, "bold italic underline"))
# 将标签控件放置在主窗口内
text.pack()
# 添加按钮控件,以及按钮的文本,并通过command参数设置关闭窗口的功能
button=tk.Button(app,text="关闭",command=app.quit)
# 将按钮控件放置在主窗口内
button.pack(side="bottom")

# 开启主循环,让窗口处于显示状态
app.mainloop()

执行以上代码,运行结果如下图:

(2)为窗口添加控件

前面我们已经通过Tkinter中的Tk()方法创建了一个简单的主窗口,并且创建了一个标签控件,这里的主窗口相当于画板,其他的控件都要建立在主窗口之上。主窗口是一切控件的基础,所有的控件的都需要通过主窗口来显示。Tkinter提供了许多常用的GUI控件(又称组件、小部件等等)如按钮(Button)、标签(Label)、文本输入框(Entry)、选择框(Radiobutton)、菜单栏(Menu)、滚动条(Scrollbar)等等,不同的控件由于形状和功能不同,都有各自的特征和属性。

众所周知,一个完整的GUI程序,其实是由有许多小的控件(组件)构成的,在学习Tkinter的GUI程序开发过程中,不仅要学会如何摆放这些控件,还要掌握各种控件的功能、属性,只有这样才能开发出一个用户友好的界面,使用户能够通过点击按钮、输入文本等方式与程序交互。下面演示Tkinter中如何添加常用的GUI控件,具体代码如下:

动手练一练:

# 导入tkinter模块,用于创建GUI应用程序
import tkinter as tk
from tkinter import messagebox

# 创建一个主窗口对象
app = tk.Tk()
# 设置窗口标题,也就是窗口的名字
app.title("添加控件示例")
# 设置窗口大小,这里的乘号不是“*”,而是小写英文字母“x”
app.geometry("300x720")

# 创建一个标签控件(Label)
label = tk.Label(app, text="这是一个标签")
# 将标签控件添加到窗口中,设置上下控件的间距为5个像素
label.pack(pady=5)

# 创建一个“单行文本输入框”控件(Entry),用户可以输入文字,但只能在一行输入
entry = tk.Entry(app, width=30)
# 将“单行文本框”控件添加到窗口中,设置上下控件的间距为5个像素
entry.pack(pady=5)
# 在位置0插入默认文本
entry.insert(0, "这是单行文本框控件,可编辑") 

# 创建普通按钮控件(Button)
button = tk.Button(app, text="这是一个普通按钮")
# 将按钮控件添加到窗口中,设置上下控件的间距为5个像素
button.pack(pady=5)

# 创建“多行文本输入框”控件(Text),用户可以输入多行文字,自由换行
# width表示一行可见的字符数;height表示显示的行数
# 设置undo=True开启“撤销”功能,输入后可以随时“撤销”返回
text = tk.Text(app, width=30, height=4, undo=True)
# 将“多行文本框”控件添加到窗口中,设置上下控件的间距为5个像素
text.pack(pady=5)
# 通过“insert” 或 “end” 索引号插入默认文本
text.insert("insert", "这是多行") 
text.insert("end", "文本框控件,可编辑") 

# 创建“多选按钮”控件(Checkbutton)
check_button = tk.Checkbutton(app, text="这是一个多选按钮")
# 将“多选按钮”控件添加到窗口中
check_button.pack()

# 创建“单选按钮”控件(Radiobutton)
radio_button = tk.Radiobutton(app, text="这是一个单选按钮")
# 将“单选按钮”控件添加到窗口中
radio_button.pack()

# 创建容器控件(Frame),作为一个小容器
frame = tk.Frame(app)
# 将容器控件添加到窗口中
frame.pack()
# 在frame容器里面创建Label标签控件(Label)
label_left = tk.Label(frame, text="这是一个数字选择控件:")
# 把Label标签放在frame容器里面的左边,并设置左右控件的间距为3个像素
label_left.pack(side="left", padx=3)
# 在frame容器里面创建“数字选择”控件(Spinbox),设置选择最小值为0,最大值为100,宽度为5个像素
# “数字选择”控件用于输入整数,它允许用户通过点击上下箭头或使用键盘来增减数值
spinbox = tk.Spinbox(frame, from_=0, to=100, width=5)
# 将“数字选择”控件放在frame容器里面的右边,并设置左右控件的间距为3个像素
spinbox.pack(side="right", padx=3)

# 创建一个StringVar变量,用于存储选中的值
stringvar = tk.StringVar()
# 设置下拉菜单默认被选中的值为“这是选项菜单”
stringvar.set("这是选项菜单")
# 创建“选项菜单”控件(OptionMenu),用户可以从下拉菜单中选择一个值,但是不能自己输入。
optionmenu = tk.OptionMenu(app, stringvar, "python", "php", "java", "javascript", "c")
# 将“选项菜单”控件添加到窗口中
optionmenu.pack()

# 创建一个“列表框”控件(Listbox)
listbox = tk.Listbox(app, width=30, height=4)
# 将“列表框”控件添加到窗口中,设置上下控件的间距为5个像素
listbox.pack(pady=5)
# i表示索引,item表示值,根据索引值的位置依次插入
# enumerate()函数可以获取序列中每个元素的索引和值
for i,item in enumerate(["这是列表框控件1","这是列表框控件2","这是列表框控件3"]):
    listbox.insert(i,item)

# 创建一个顶级“菜单栏”控件(Menu)
mainmenu = tk.Menu(app)
# 创建一个名为 "这是菜单" 的普通菜单项
mainmenu.add_command(label="这是菜单")
# 创建一个带下拉标志的菜单项
# tearoff=False表示不允许菜单项被拖出成为独立窗口
gamemenu = tk.Menu(mainmenu, tearoff=False)
# 将"游戏"菜单项作为下拉菜单添加到顶级菜单中
mainmenu.add_cascade(label="游戏",menu=gamemenu)
# 在"游戏"下拉菜单中添加选项
gamemenu.add_command(label="简单")
gamemenu.add_command(label="普通")
gamemenu.add_command(label="困难")
gamemenu.add_command(label="噩梦")
# 创建一个名为 "帮助" 的普通菜单项
mainmenu.add_command(label="帮助")
# 创建一个名为 "退出" 的普通菜单项,点击后会退出窗口
mainmenu.add_command(label="退出", command=app.quit)
# 将这个菜单设置为顶层窗口的菜单
app.config(menu = mainmenu)

# 创建一个“菜单按钮”控件(Menubutton),点击后会显示下拉菜单项
menubutton = tk.Menubutton(app, text="点击后出现下拉菜单", relief="raised")
# 将“菜单按钮”控件添加到窗口中,设置上下控件的间距为5个像素
menubutton.pack(pady=5)
# 创建一个带下拉标志的菜单项
# tearoff=False表示不允许菜单项被拖出成为独立窗口
filemenu = tk.Menu(menubutton, tearoff=False)
# 菜单按钮被点击后的下拉菜单中添加选项
filemenu.add_command(label="打开")
filemenu.add_command(label="保存")
filemenu.add_command(label="退出", command=app.quit)
# 将这个菜单设置为菜单按钮
menubutton.config(menu = filemenu)

# 定义子窗口函数
def newwind():
    # 创建一个新的窗口
    winNew = tk.Toplevel(app)
    # 设置窗口大小
    winNew.geometry("320x240")
    # 设置窗口标题
    winNew.title("新窗体")
    # 创建标签控件
    label = tk.Label(winNew, text="这是一个新的窗体")
    # 将标签控件添加到窗口中
    label.pack()
# 创建按钮控件(Button),点击后会弹出一个新的窗口
# command参数用来执行按钮关联的回调函数。当按钮被点击时,会执行newwind()函数
newmenu = tk.Button(app, text="点击后会弹出新的窗口", command=newwind)
# 将按钮控件添加到窗口中,设置上下控件的间距为5个像素
newmenu.pack(pady=5)

# 定义对话框函数
def showmessage():
    # 弹出一个提示对话框
    messagebox.showinfo("提示", "这是一个提示对话框")
# 创建按钮控件(Button),点击后会弹出一个提示对话框
# command参数用来执行按钮关联的回调函数。当按钮被点击时,会执行showmessage()函数
showmenu = tk.Button(app, text="点击后会弹出提示对话框", command=showmessage)
# 将按钮控件添加到窗口中,设置上下控件的间距为5个像素
showmenu.pack(pady=5)

test = "这是消息控件,用来显示多行文本,是不可编辑的。"
# 创建一个消息控件(Message)
message = tk.Message(app, text=test, width=200)
# 用configure()方法改变背景颜色属性bg的值
message.configure(bg="red")
# 将消息控件添加到窗口中,设置上下控件的间距为5个像素
message.pack(pady=5)

# 创建一个简单的容器控件(LabelFrame),用于复杂的窗口布局。
group = tk.LabelFrame(app, text="这是一个简单的容器控件", padx=3, pady=3)
group.pack(padx=5, pady=5)
# 创建一个IntVar变量,用于存储整数值的变量
intvar = tk.IntVar()
# 创建“单选按钮”控件(Radiobutton)
r1 = tk.Radiobutton(group, text="男", variable=intvar, value=1)
r1.pack()
r2 = tk.Radiobutton(group, text="女", variable=intvar, value=2)
r2.pack()

# 创建一个滚动条控件(Scrollbar),默认为垂直方向
sbar1 = tk.Scrollbar(app, orient="vertical")
# 将滚动条放置在右侧,并设置当窗口大小改变时滚动条会沿着垂直方向延展
sbar1.pack(side="right", fill="y")
# 创建水平滚动条,默认为水平方向,当拖动窗口时会沿着X轴方向填充
sbar2 = tk.Scrollbar (app, orient="horizontal")
# 将滚动条放置在底部,并设置当窗口大小改变时滚动条会沿着水平方向延展
sbar2.pack(side="bottom", fill="x")
# 创建列表框控件,并添加两个滚动条(分别在垂直和水平方向),使用set()进行设置
mylist = tk.Listbox(app, width=200, height=5, xscrollcommand=sbar2.set, yscrollcommand=sbar1.set)
# 从1到20遍历出20行数据
for i in range(20):
    mylist.insert("end","第"+ str(i+1)+"行: "+"这是滚动条控件,用来显示垂直和水平方向的两个滚动条。"+ "\n" )
# 当窗口改变大小时会在X与Y方向填满窗口
mylist.pack(side="left",fill="both")
# 使用command关联控件的yview、xview方法
sbar1.config(command = mylist.yview)
sbar2.config(command = mylist.xview)

# 开启主循环,让窗口处于显示状态
app.mainloop()

执行以上代码,运行结果如下图:

上面的例子中,我们通过主窗口创建了几个常用的GUI控件,下表列出了Tkinter中常用的控件:

控件类型 控件名称 控件作用
Button 按钮 点击按钮时触发/执行一些事件(函数)
Canvas 画布 提供绘制图,比如直线、矩形、多边形等
Checkbutton 复选框 多项选择按钮,用于在程序中提供多项选择框
Entry 文本框输入框 用于接收单行文本输入
Frame 框架(容器)控件 定义一个窗体(根窗口也是一个窗体),用于承载其他控件,即作为其他控件的容器
Lable 标签控件 用于显示单行文本或者图片
LableFrame 容器控件 一个简单的容器控件,常用于复杂的窗口布局。
Listbox 列表框控件 以列表的形式显示文本
Menu 菜单控件 菜单组件(下拉菜单和弹出菜单)
Menubutton 菜单按钮控件 用于显示菜单项
Message 信息控件 用于显示多行不可编辑的文本,与 Label控件类似,增加了自动分行的功能
messageBox 消息框控件 定义与用户交互的消息对话框
OptionMenu 选项菜单 下拉菜单
PanedWindow 窗口布局管理组件 为组件提供一个框架,允许用户自己划分窗口空间
Radiobutton 单选框 单项选择按钮,只允许从多个选项中选择一项
Scale 进度条控件 定义一个线性“滑块”用来控制范围,可以设定起始值和结束值,并显示当前位置的精确值
Spinbox 高级输入框 Entry 控件的升级版,可以通过该组件的上、下箭头选择不同的值
Scrollbar 滚动条 默认垂直方向,鼠标拖动改变数值,可以和 Text、Listbox、Canvas等控件配合使用
Text 多行文本框 接收或输出多行文本内容
Toplevel 子窗口 在创建一个独立于主窗口之外的子窗口,位于主窗口的上一层,可作为其他控件的容器