GUI 图形用户界面编程
GUI(Graphics User Interface),即图形用户界面编程,我们可以通过 python 提供的丰富的组件,快速的实现使用图形界面和用户交互。
GUI 编程类似于“搭积木”,将一个个组件(Widget)放到窗口中。如下是 windows 中的画图软件,就是一个典型的GUI 程序:
上面的各种按钮、菜单、编辑区域等都是一个个组件,它们都放置到窗口中,并通过增加“对事件的处理成为一个完整的程序
常用的 GUI 库
1.Tkinter
tkinter(Tk interface)是 Python 的标准 GUI 库,支持跨平台的 GUI 程序开发。tkinter 适合小型的 GUI 程序编写,也特别适合初学者学习 GUI 编程。
2.wxPython
wxPython 是比较流行的GUI 库,适合大型应用程序开发,功能强于 tkinter ,整体设计框架类似于 MFC(Microsoft Foundation Classes 微软基础类库)。
3.PyQT
Qt 是一种开源的 GUI 库,适合大型 GUI 程序开发,PyQT是Qt 工具包标准的 Python 实现。我们也可以使用 Qt Desginer 界面设计器快速开发 GUI 应用程序。
tkinter 模块
学习 API 最好的来源就是官方提供的文档:tkinter 官方网址:https://docs.python.org/3.7/library/tk.html
或者:http://effbot.org/tkinterbook/ (相对规整,适合初学者查找)
GUI 编程的核心步骤和第一个 GUI 程序
基于 tkinter 模块创建 GUI 程序包含如下 4 个核心步骤:
1.创建应用程序主窗口对象(也称:根窗口)
(1) 通过类 Tk 的无参构造函数
from tkinter import *
root =Tk()
2.在主窗口中,添加各种可视化组件,比如:按钮(Button)、文本框(Label)等。
btn01= Button(root)
btn01["text"] = "点我就送花"
3.通过几何布局管理器,管理组件的大小和位置 ```py
btn01.pack()
``
4.事件处理
(1)通过绑定事件处理程序,响应用户操作所触发的事件(比如:单击、双击等)
def songhua(e):
messagebox.showinfo("Message","送你一朵玫瑰花,请你爱上我")
print("送你 99 朵玫瑰花")
btn01.bind("<Button-1>",songhua)
【示例】使用 tkinter 模块,创建 GUI 应用程序,并实现点击按钮的事件处理
from tkinter import *
from tkinter import messagebox
root= Tk()
btn01= Button(root)
btn01["text"] = "点我就送花"
btn01.pack()
def songhua(e):
messagebox.showinfo("Message","送你一朵玫瑰花,请你爱上我")
print("送你 99 朵玫瑰花")
btn01.bind("<Button-1>",songhua)
root.mainloop() #调用组件的 mainloop 方法,进入事件循环
tkinter 主窗口
主窗口位置和大小
通过 geometry(‘wxh±x±y’)进行设置。w 为宽度,h 为高度。
+x 表示距屏幕左边的距离;-x 表示距屏幕右边的距离;+y表示距屏幕上边的距离;-y 表示距屏幕下边的距离。
【示例】测试 tkinter 主窗口位置和大小的设置
from tkinter import *
from tkinter import messagebox
root = Tk()
root.title('我的第一个GUI程序')
root.geometry('500x300+100+200')
btn01=Button(root)
btn01['text']='点我就送花'
btn01.pack()
def songhua(e):
messagebox.showerror('Message','送你一朵花')
print('送你99朵玫瑰花')
#事件绑定
btn01.bind('<Button-1>',songhua)
root.mainloop()
执行结果:
GUI 编程整体描述
图形用户界面是由一个个组件组成,就像小孩“搭积木”一样最终组成了整个界面。有的组件还能在里面再放置其他组件,我们称为“容器”。Tkinter 的 GUI 组件关系图如下:
图tkinter 中 GUI 组件的继承关系图
根据上图所示,我们依次讲解这些类的基本作用。
·Misc 和 Wm:
Tkinter 的 GUI 组件有两个根父类,它们都直接继承了 object 类:
·Misc:它是所有组件的根父类。
·Wm:它主要提供了一些与窗口管理器通信的功能函数。
·Tk
Misc 和 Wm 派生出子类 Tk,它代表应用程序的主窗口。一般应用程序都需要直接或间接使用 Tk。
·Pack、Place、Grid
Pack、Place、Grid 是布局管理器。布局管理器管理组件的:大小、位置。通过布局管理器可以将容器中的组件实现合理的排布。
·BaseWidget
BaseWidget 是所有组件的父类
·Widget
Widget 是所有组件类的父类。Widget 一共有四个父类:BaseWidget、Pack、Grid、Place。意味着,所有 GUI 组件同时具备这四个父类的属性和方法。
【注】想观察类的层次结构可以在类定义处的类名上单击右键,选择 Diagram–>show Diagram。
常用组件汇总列表
GUI 应用程序类的经典写法
本节采用了面向对象的方式,更加合理的组织代码。通过类 Application 组织整个 GUI 程序,类 Application继承了 Frame 及通过继承拥有了父类的特性。通过构造函数__init__()初始化窗口中的对象,通过 createWidgets()方法创建窗口中的对象。
Frame 框架是一个 tkinter 组件,表示一个矩形的区域。
Frame 一般作为容器使用,可以放置其他组件,从而实现复杂的布局。
【示例】标准的 GUI 程序类的写法
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self,master=None):
super().__init__(master)
self.master=master
self.pack()
self.createWidget()
def createWidget(self):
#创建组件
self.btn01=Button(self)
self.btn01['text']='点击送花'
self.btn01.pack()
self.btn01['command']=self.songhua
#创建一个退出按钮
self.btnQuit=Button(self,text='退出',command=root.destroy)
self.btnQuit.pack()
def songhua(self):
messagebox.showinfo('送花','送你99朵玫瑰花')
root=Tk()
root.geometry('400x100+200+300')
root.title('一个经典的GUI程序类的测试')
app=Application(master=root)
root.mainloop()
简单组件
Label 标签
Label(标签)主要用于显示文本信息,也可以显示图像。
Label(标签)有这样一些常见属性:
1.width,height:
用于指定区域大小,如果显示是文本,则以单个英文字符大小为单位(一个汉字宽度占 2 个字符位置,高度和英文字符一样);如果显示是图像,则以像素为单位。默认值是根据具体显示的内容动态调整。
2.font
指定字体和字体大小,如:font =(font_name,size)
3.image:
显示在 Label 上的图像,目前 tkinter 只支持 gif 格式。
4.fg 和 bg
fg(foreground):前景色、bg(background):背景色
5.justify
针对多行文字的对齐,可设置 justify 属性,可选值"left",
“center” or “right”
【示例】Label(标签)的用法
from tkinter import *
class Application(Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.createWidget()
def createWidget(self):
# 创建组件
self.label01=Label(self,text='关关雎鸠',width=10,height=2,
bg='black',fg='white')
self.label01.pack()
self.label02 = Label(self, text='hebut', width=10, height=2,
bg='blue', fg='white',font=('黑体',30))
self.label02.pack()
# 显示图像
global photo
photo=PhotoImage(file='pic01.gif')
self.label03=Label(self,image=photo)
self.label03.pack()
#显示多行文本
self.label04=Label(self,text='hebut\n关关雎鸠',borderwidth=1,relief='groove',justify='right')
self.label04.pack()
if __name__=='__main__':
root=Tk()
root.geometry('400x500+200+300')
app=Application(master=root)
root.mainloop()
运行结果如下:
Options 选项详解
通过学习 Label 组件,我们发现可以通过 Options 设置组件的属性,从而控制组件的各种状态。比如:宽度、高度、颜色、位置等等。
我们可以通过三种方式设置 Options 选项,这在各种 GUI 组件中用法都一致。
1.创建对象时,使用可变参数
fred = Button(self, fg="red", bg="blue")
2.创建对象后,使用字典索引方式
fred["fg"] = "red"
fred["bg"] = "blue"
3.创建对象后,使用 config()方法
fred.config(fg="red", bg="blue")
如何查看组件的 Options 选项:
1.可以通过打印 config()方法的返回值,查看 Options 选项 print(fred.config())
2.通过在 IDE 中,点击组件对象的构造方法,进入到方法内观察:
我们可以看到如下的代码:
class Button(Widget):
"""Buttonwidget."""
def __init__(self, master=None,cnf={
}, **kw):
"""ConstructabuttonwidgetwiththeparentMASTER.
STANDARD OPTIONS
activebackground,activeforeground,anchor,
background,bitmap,borderwidth,cursor,
disabledforeground,font,foreground
highlightbackground,highlightcolor,
highlightthickness,image,justify,
padx,pady,relief,repeatdelay,
repeatinterval,takefocus,text,
textvariable,underline,wraplength
WIDGET-SPECIFIC OPTIONS
command,compound,default,height,
overrelief,state,width
"""
Widget.__init__(self, master, 'button', cnf,kw)
上面代码中有:“standard options 标准选项”和“widget-specific options 组件特定选项”。我们将常见的选项汇总如下:
Button
Button(按钮)用来执行用户的单击操作。Button 可以包含文本,也可以包含图像。按钮被单击后会自动调用对应事件绑定的方法。
【示例】Button 按钮用法(文字、图片、事件)
#测试Button组件的基本用法,使用面向对象的方式
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self, master=None): # super()代表的是父类的
super().__init__(master)
self.master = master
self.pack()
self.createWidget()
def createWidget(self):
#创建组件
self.btn01 = Button(root, text="登录",width=6,height=3,anchor=CENTER,command=self.login)
self.btn01.pack()
global photo
photo = PhotoImage(file="pic01.gif")
self.btn02 = Button(root,image=photo,command=self.login)
self.btn02.pack()
self.btn02.config(state="disabled") #设置按钮为禁用
def login(self):
messagebox.showinfo("学习系统", "登录成功!欢迎开始学习!")
if __name__ == '__main__':
root = Tk()
root.geometry("400x400+200+300")
app = Application(master=root)
root.mainloop()
运行结果:
Entry 单行文本框
Entry 用来接收一行字符串的控件。如果用户输入的文字长度长于 Entry 控件的宽度时, 文字会自动向后滚动。如果想输入多行文本, 需要使用 Text 控件。
【示例】Entry 单行文本框实现简单登录界面
# 测试 Entry 组件的基本用法,使用面向对象的方式
from tkinter import *
from tkinter import messagebox
class Application(Frame):
def __init__(self, master=None): # super()代表的是父类的定义,而不是父类对象
super().__init__(master)
self.master = master
self.pack()
self.createWidget()
def createWidget(self):
# 创建登录界面的组件
self.label01 = Label(self, text="用户名")
self.label01.pack()
# StringVar 变量绑定到指定的组件。
# StringVar 变量的值发生变化,组件内容也变化;
# 组件内容发生变化,StringVar 变量的值也发生变化。 v1 = StringVar()
v1 = StringVar()
self.entry01 = Entry(self, textvariable=v1)
self.entry01.pack()
v1.set("admin")
print(v1.get())
print(s