GUI(Graphics User Interface)图形用户界面编程。我们可以通过 python 提供的丰富的组件,快速的实现使用图形的界面和用户交互。 GUI 编程类似于“搭积⽊”,将⼀个个组件(Widget)放到 窗⼝中。
如下是 windows 中的画板工具,就是典型的GUI程序:
官方工具包Tkinter,是python的一个标准库,内置在python解释器环境里,无需安装就可以直接使用,python自带的IDLE就是用Tkinter来开发的窗口程序。Tkinter是建立在Tk技术上的,通过Tkinter做出的程序在Unix和windows平台上都可以使用,直接进行展示。GUI自带的、可以编辑的界面,可以实现很多直观的功能,图像、登录的窗口等等,比如开发计算器、画板工具、创建记事本的应用程序等都可以实现,可以实现键盘输入、输出窗口以及跟用户的交互体验。
界面上的各种按钮、菜单、编辑区域等都是⼀个个组件组成,对组件进行搭配组合放置到窗口中来执行相应的功能,并通过增加对事件处理成为一个完整的程序,点击相应的按钮实现对应的功能。
Tkinter是python标准的GUI库,支持跨平台的GUI程序开发,适合小型的GUI程序编写,适合初学者学习。
Tk + interface = Tkinter
wxpython是比较流行的GUI库,适合进行大型程序的开发,功能比较强大,整体设计框架类似于MFC(Microsoft Foundation Classes 微软基础类库)。
Qt 是⼀种开源的 GUI 库,适合⼤型 GUI 程序开发,PyQT是 Qt ⼯具包跟交互式语言python结合的来实现Qt界面,即是跟标准的 Python 语言结合的实现。我们也可以使⽤自带的 Qt Desginer 界⾯设计器快速开发 GUI 应⽤程序。
窗口会一直停留在界面,等待用户点击tk上的叉号,程序才能运行结束。
可以在导入的时候 起个别名,方便调用。
import tkinter as tk # 调用的时候直接用tk就可以了
from tkinter import * # 不建议使用,好比工具箱里由很多工具,
而我们使用的时候只用其中的一项,全部取出的化会导致内存的占用
图形化编程要求首先要有窗口(画板、容器),command是Button里的一个配置项(option)用来指定调用的函数,点击按钮触发事件;也可以添加 高度,字体等
# 导入
import tkinter
from tkinter import messagebox # 消息框
# 1.创建应用程序主窗口
# 通过Tk()类创建一个窗口
root = tkinter.Tk() # 运行完就关闭了,需要加入停留让窗口一直停留
# callback 回掉函数---事件
def massage_1():
# 显示消息框
messagebox.showinfo('Message','文档说明信息,点击关闭')
# 2.在主窗口中,添加各种可视化的组件(菜单、按钮)
# 4.事件处理
bt =tkinter.Button(root, text='按钮说明',command=massage_1)
# 创建按钮,放在主窗口对象上面,此时函数是用按钮调用,不加后面的小括号
# 3.通过几何布局管理器,管理组件的大小及组件的位置,
bt.pack()
bt1 =tkinter.Button(root, text='按钮说明1') # 创建按钮,放在主窗口对象上面
bt1.pack() # 按钮从上至下排列,此时的按钮没有功能,需要绑定事件
# 需要加入消息循环,让窗口停留在界面上
root.mainloop()
import tkinter
from tkinter import messagebox # 消息框
# 1.创建应用程序主窗口
root = tkinter.Tk()
def massage_1(event): # 此方法下函数必须加形参
messagebox.showinfo('Message','文档说明信息,点击关闭')
# 2.在主窗口中,添加各种可视化的组件(菜单、按钮)
bt =tkinter.Button(root, text='按钮说明')
# 3.通过几何布局管理器,管理组件的大小及组件的位置,
bt.pack()
# 4.事件处理,通过事件绑定,Button-1 鼠标左键
bt.bind('' , massage_1) # 绑定(bind)比按钮命令(command)应用广泛
root.mainloop()
genometry(wxh±x±y) w 为宽度,h 为⾼度,中间用x。
+x 表示距屏幕左边的距离;-x 表示距屏幕右边的距离;
+y 表示距屏幕上边的距离;-y 表示距屏幕下边的距离。
import tkinter
from tkinter import messagebox # 消息框
root = tkinter.Tk() # 默认窗口比较小,位置在左上方
# 标题
root.title('标题')
# 设置窗口的大小以及出现的位置
# 300x300是窗口大小,900是距离屏幕左侧的距离,300是距上方的距离
root.geometry('300x300+900+300')
# 更改默认的图标
root.iconbitmap('images/favicon.ico')
# 设置界面的背景色,可以用英文单词,也可以用十六进制
# root['background'] = 'red'
root['background'] = '#00ffff'
# 设置外形
# 设置透明度 范围0-1,0是完全透明,1是完全不透明
root.attributes('-alpha', 0.5)
# 设置工具栏样式,窗口的最大、最小化等等
# True 只有关闭按钮,没有图标,False为正常窗体的样式
root.attributes('-toolwindow', True)
# 设置全屏,慎用
# root.attributes('-fullscreen',True)
# 窗口置顶,运行时窗口永远在程序的最上方
root.attributes('-topmost', True)
# 设置脱离工具栏,True没有上面的工具栏按钮,False正常显示,一般不用
# root.overrideredirect(True)
def massage_1(event):
messagebox.showinfo('Message','文档说明信息,点击关闭')
bt =tkinter.Button(root, text='按钮说明')
bt.pack()
bt.bind('' , massage_1)
root.mainloop()
设置默认图标的时候 images文件夹和代码在同一文件夹下。设置背景颜色的时候可以用十六进制颜色表进行对照。
GUI项目最好用面向对象来写程序逻辑,方便修改、拓展及调试。
Frame是组件,在此为画纸,我们可以直接在画板上作画,也可以先写到画纸上,然后再把画纸放到画板上,画板上可以容纳多张画纸相互重叠,使得布局和程序更加合理和方便。在画图工具中的各个组件(如剪贴板,图像,工具,形状等)都写在画纸上,然后再把画纸写到窗口的画板上,这样编程搭配会比较方便。
import tkinter
from tkinter import messagebox,Frame,Button
#定义类继承于画纸对象,然后把画纸放到画板上
class Application(Frame):
'''经典的GUI程序类的写法'''
def __init__(self,master=None):# master模板容器,画纸放到哪
# 继承方法,父类的重新定义
super().__init__(master) # 定义属性
self.master = master
self.pack() # 画纸几何布局,默认摆放
self.CreatWidget() # 创建示例对象时,自动进行调用
def CreatWidget(self):
'''创建组件'''
self.bt = Button(self)
# self.bt = Button(self,text='按钮说明')
self.bt['text'] = '按钮说明' # 与上一行代码等同
self.bt.pack() # 默认布局
# 事件绑定
self.bt.bind('' , self.massage_1) # 绑定,方法里必须的有形参
# self.bt['command'] = self.massage_1 # 用此方法的时候massage_1内不能有形参
# 如果有形参,调用时候得进行传参,否则方法里就不能有形参 def massage_1(self)
def massage_1(self,event):
messagebox.showinfo('Message', '文档说明信息,点击关闭')
if __name__ == '__main__': # 程序入口,里面的本文件内调用,其他程序访问不到
root = tkinter.Tk() # 创建主窗口
root.title('标题-经典GUI程序类的测试')
root.geometry('300x300+900+300')
# 创建画纸对象放到root画板上
Application(master=root)
root.mainloop() # 消息循环
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""
属性 | 说明 |
---|---|
text | 标签显示的文本 |
font | 设置文本的字体和大小 |
fg(foreground) | 字体的颜色 |
bg(background) | 标签的背景色 |
width | 标签的宽度(一个中文字体的宽为单位) |
height | 标签的高度(一个中文字体的高为单位) |
padx | 文字到边框的距离,水平方向 |
pady | 文字到边框的距离,垂直方向 |
bd(bordenwidth) | 边框的宽度 |
relief | 边框的样式 |
justify | 文本对齐方式,默认居中 |
image | 图片 |
compound | 图片与文字的混搭 |
anchor | 方位 |
import tkinter
from tkinter import Frame,Label,PhotoImage
'''测试Label组件的基本使用'''
#定义类继承于画纸对象
class Application(Frame):
def __init__(self,master=None):# master模板容器,画纸放到哪
# 继承方法,父类的重新定义
super().__init__(master) # 定义属性
self.master = master
self.pack() # 画纸几何布局,默认摆放
self.CreatWidget() # 创建示例对象时,自动进行调用
def CreatWidget(self):
'''创建标签组件,显示文字和图像'''
self.label01 = Label(self, text='图形编程',width=10,height=2,bg='black',fg='white')
self.label01['text'] = '替换文字'
self.label01.pack() # 默认布局
self.label02 = Label(self, text='图形编程', width=10, height=2, bg='blue', fg='white',font=('黑体',30))
self.label02.pack() # 默认布局
# 显示图像,gif,png均可
global photo
photo = PhotoImage(file='images/shou.gif')
self.label03 = Label(self,image=photo)
self.label03.pack()
# borderwidth为边框宽度,relief为边框样式,justify默认居中
self.label04 = Label(self, text='图形编程\n 非常简单可视化的编程', borderwidth=5,relief='groove',justify='right')
self.label04.pack() # 默认布局
if __name__ == '__main__': # 程序入口,里面的本文件内调用,其他程序访问不到
root = tkinter.Tk() # 创建主窗口
root.title('标题-经典GUI程序类的测试')
root.geometry('300x300+900+300')
# 创建画纸对象放到root画板上
Application(master=root)
root.mainloop() # 消息循环
Button(按钮)⽤来执⾏⽤户的单击操作。Button 可以包含 ⽂本,也可以包含图像。按钮被单击后会⾃动调⽤对应事件 绑定的⽅法。
from tkinter import *
from tkinter import messagebox
#定义类继承于画纸对象
class Application(Frame):
'''经典的GUI程序类的写法'''
def __init__(self,master=None):# master模板容器,画纸放到哪
# 继承方法,父类的重新定义
super().__init__(master) # 定义属性
self.master = master
self.pack() # 画纸几何布局,默认摆放
self.CreatWidget() # 创建示例对象时,自动进行调用
def CreatWidget(self):
'''创建组件'''
# NE 文字在按钮上的方位,东北角
self.btn01 = Button(root,text='登录',width=6,height=3,anchor=NE,command=self.login)
self.btn01.pack()
global photo
photo = PhotoImage(file='images/start.gif')
# 直接把按钮放在画板root上
self.btn02 = Button(root,image=photo,command=self.login)
self.btn02.pack()
# 也可以设置按钮禁用,比如会员可以点击,非会员禁用
self.btn02.config(state='disable') # 设置按钮禁用
def login(self):
messagebox.showinfo('学习系统', '登录成功,开始学习')
if __name__ == '__main__': # 程序入口,里面的本文件内调用,其他程序访问不到
root = Tk() # 创建主窗口
root.title('标题-经典GUI程序类的测试')
root.geometry('300x300+900+300')
# 创建画纸对象放到root画板上
Application(master=root)
root.mainloop() # 消息循环
单行文本框 Entry ⽤来接收一行字符串的控件。如果用户输⼊的文字长度长于 Entry 控件的宽度时, ⽂字会自动向后滚动。如果想输入多行文本, 需要使用 Text 控件。通常用户账号密码输入的登录框,比对后台的数据库,对的话显示登录成功,不正确显示输入错误。
from tkinter import *
from tkinter import messagebox
#定义类继承于画纸对象
class Application(Frame):
'''经典的GUI程序类的写法'''
def __init__(self,master=None):# master模板容器,画纸放到哪
# 继承方法,父类的重新定义
super().__init__(master) # 定义属性
self.master = master
self.pack() # 画纸几何布局,默认摆放
self.CreatWidget() # 创建示例对象时,自动进行调用
def CreatWidget(self):
'''创建组件'''
self.label01 = Label(self,text='用户名')
self.label01.pack()
# 获取输入框的信息,输入框的内容是可变的
# v1是可变的,创建变量StringVar绑定到组件上,StringVar发生变化,组件内容entry01的值也会发生变化
v1 = StringVar()
self.entry01 = Entry(self,textvariable=v1)
self.entry01.pack()
v1.set('admin') # 设置默认值为admin
print(v1.get()) # 获取变量的信息
print(self.entry01.get()) # 获取输入框的信息
self.label02 = Label(self, text='密码')
self.label02.pack()
v2 = StringVar()
self.entry02 = Entry(self,textvariable=v2)
self.entry02.pack()
Button(self,text='登录',command=self.login).pack()
def login(self):
# 用组件接受用户输入的信息
username = self.entry01.get()
psd = self.entry02.get()
print('去数据库比对账号和密码')
print('用户名' + username)
print('密码' + psd)
if username == 'xuexi001' and psd == '123456':
messagebox.showinfo('学习系统', '登录成功,开始学习')
else:
messagebox.showinfo('学习系统', '登录失败,用户名或密码错误!')
if __name__ == '__main__': # 程序入口,里面的本文件内调用,其他程序访问不到
root = Tk() # 创建主窗口
root.title('标题-经典GUI程序类的测试')
root.geometry('300x300+900+300')
# 创建画纸对象放到root画板上
Application(master=root)
root.mainloop() # 消息循环