初学者对于“图形用户界面”这个名词一定会很迷茫,其实在我们的日常工作与学习中,我们经常用到“图形用户界面”。比如,当我们打开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 | 子窗口 | 在创建一个独立于主窗口之外的子窗口,位于主窗口的上一层,可作为其他控件的容器 |