1.Python Tkinter(GUI图形界面):
a. What's Tkinter(Tkinter 是什么)?
Tkinter是Python自带的一个GUI库,他可以将我们在command line中的操作进行可视化操作。并且它简单的构造, 多平台, 多系统的兼容性, 能让它成为让你快速入门定制窗口文件的好助手. 它在 python 窗口视窗模块中是一款简单型的. 所以用来入门, 熟悉 窗口视窗的使用, 非常有必要.
b. Tkinter创建窗口以及标签按钮:
我们可以通过如下代码校验你的Tkinter包是否安装成功:
python -m tkinter # 如果安装成功,那么你的桌面会弹出一个窗口,如下:
接下来,我们要自己创建一个窗口,并且在窗口中加入一个标签Label:
import tkinter as tk
window = tk.Tk() # 创建一个窗口对象
window.title('my first window') #给窗口命名
window.geometry('200x100') #定义窗口的长宽,geometry方法中传入字符串参数,字符串中应为长x宽(Note:x是小写字母x)
# Label(master = None, cnf = {}, **kw), kw参数是类似dict一样接收label组件定义的键值对
l = tk.Label(window, text='successful! created new Label', bg='green', font=('Arial', 12), width=25, height=4)
l.pack() #将定义好的label添加到window上
window.mainloop() #mainloop实际上是使用while循环实现的,因为窗口的内容是会动态变化的
接下来我们继续在窗口上创建Button按钮,并且我们实现了点击一次按钮Label消失,再点击一次按钮Label重新显示:
import tkinter as tk
window = tk.Tk() # 创建一个窗口对象
window.title('my first window') #给窗口命名
window.geometry('200x100') #定义窗口的长宽,geometry方法中传入字符串参数,字符串中应为长x宽(Note:x是小写字母x)
# Label(master = None, cnf = {}, **kw), kw参数是类似dict一样接收label组件定义的键值对
#l = tk.Label(window, text='successful! created new Label', bg='green', font=('Arial', 12), width=25, height=4)
var = tk.StringVar() #将label中的文本动态化设置,可以利用var.set()方法设置textvariable
l = tk.Label(window, textvariable=var, bg='green', font=('Arial', 12), width=25, height=4)
l.pack() #将定义好的label添加到window上
is_Hidden = False # 设置一个flag变量,用来判断现在窗口的label是显示的还是未显示的
def hidden_me():
global is_Hidden
if is_Hidden == False:
is_Hidden = True
var.set('click me and hidden')
else:
is_Hidden = False
var.set('')
var1 = tk.StringVar()
var1.set('hidden')
#Button(master, option = value, ..), command是点击后发生什么效果的函数
b = tk.Button(window, textvariable = var1, width = 12, height = 2, command = hidden_me)
b.pack() # 将button显示在窗口中
window.mainloop() #mainloop实际上是使用while循环实现的,因为窗口的内容是会动态变化的
点击Button之前:
点击Button之后:
再点击hidden Button,Label又会隐藏。
c. Tkinter在窗口中使用输入框Entry & 文本框Text:
我们在网页中经常会遇到输入框和文本框两种常用的表单项,那么,在Tkinter中有Entry和Text对应了这两种常用的框。我们接下来要做一个小案例(在输入框输入文本,然后设置两个button,button1是在你点击文本框内容的光标处插入输入框中的文本。button2是在文本框内容的末尾插入输入框的文本)
import tkinter as tk
window = tk.Tk()
window.title('My Window')
window.geometry('300x200')
e = tk.Entry(window, show = None) # show = None:输入字符可见, show = '*':
e.pack()
# 在光标处插入entry输入框的数据
def insert_point():
var = e.get()
t.insert('insert', var)
# 在文本末尾插入entry输入框的数据
def insert_end():
var = e.get()
t.insert('end', var)
b1 = tk.Button(window, text = 'insert point', width = 15, height = 2, command = insert_point)
b1.pack()
b2 = tk.Button(window, text = 'insert end', width = 15, height = 2,command = insert_end)
b2.pack()
t = tk.Text(window, height = 5) # height定义文本框有多少行
t.pack()
window.mainloop()
初始状态:
点击button1 在光标处插入:
![](/Users/liyan/Library/Application Support/typora-user-images/image-20200712223347218.png)
![](/Users/liyan/Library/Application Support/typora-user-images/image-20200712223421949.png)
点击button2在文本框末尾插入:
这样就使用Entry & Text完成了一个小实例
Note:以上例子在PyCharm中运行,button上的文本不会显示,我的电脑是Mac,Python版本3.7+,在命令行运行脚本既可以看到button中的文本属性。大佬如果知道原因可以给我留言。
d. Tkinter中Listbox的使用:
我们经常在网页上使用列表框,就比如选择你在填写表单的时候,你需要填写你的学历,这时候会有一个下拉列表框,上面写着:初中毕业,中专,高中,大学等常见的学历选项,你下拉选择好,点击后就会自动给您填上,我们下面做一个小例子:使用Tikinter中的listbox实现点击下拉列表框中的value,在点击Button,将value打印到窗口设置的Label中。
import tkinter as tk
window = tk.Tk()
window.title('My Listbox')
window.geometry('300x200')
var1 = tk.StringVar()
l = tk.Label(window, textvariable = var1, bg = 'yellow', font=('Arial', 12), width=25, height=4)
l.pack()
def print_selection():
tmp = lb.get(lb.curselection()) #curselection()表示的是获取当前列表所选中的
var1.set(tmp) # 将当前所选中的listbox的value设置到Lable上。
b = tk.Button(window, text = 'print list selection', width = 12, height = 2, command = print_selection)
b.pack()
var2 = tk.StringVar()
var2.set(('first', 'second', 'third', 'fourth'))
lb = tk.Listbox(window, listvariable = var2) # 初始化listbox时,将var2赋值给lb初始化
list_items = [1, 2, 3, 4]
for item in list_items:
lb.insert('end', item)
# 还可以使用insert(index, value)形式,按照list的下标插入value
# lb.insert(1, 'one')
# 使用delete(index)形式,删除list中index的元素
lb.pack()
window.mainloop()
初始化:
![](/Users/liyan/Library/Application Support/typora-user-images/image-20200713210112094.png)
选中列表框任意一个value打印到Label上:
e. Tkinter中RadioButton的使用
大家应该都在网上做过测试,像单选题的那种选择框就是RadioButton的典型应用。我们将做一个ABC三个选项,当你选择某一个选项时,点击后,窗口的Label就会打印出你当前选的值是什么的例子:
import tkinter as tk
window = tk.Tk()
window.title('My RadioButton')
window.geometry('400x400')
var = tk.StringVar()
l = tk.Label(window, text = 'empty', bg = 'red', font = ('Arial', 12), width = 25, height = 5)
l.pack()
def choose_button():
l.config(text = 'you have choosen ' + var.get()) #config()给Label进行属性设置,这里获取当前选项的value进行绑定
# RadioButton中variable将所选中的value值绑定到var变量中,方便在点击后,给label进行绑定
r1 = tk.Radiobutton(window, text = 'Option A', variable = var, value = 'A', command = choose_button)
r1.pack()
r2 = tk.Radiobutton(window, text = 'Option B', variable = var, value = 'B', command = choose_button)
r2.pack()
r3 = tk.Radiobutton(window, text = 'Option C', variable = var, value = 'C', command = choose_button)
r3.pack()
window.mainloop()
初始:
![](/Users/liyan/Library/Application Support/typora-user-images/image-20200713212826346.png)
这里其实应该不是三个-号,是mac系统才有的,windows系统应该是正常的。
choose 后:
f. Tkinter中Scale(滚动条)的使用:
我们经常会在某些特定的场合使用滚动条,但是那种滚动条使用比较多的可能是网站登录使用的滚动验证码。我们必须把残缺的图案滑动到指定的缺口令其重合。我们现在就做一个滚动条的小例子:滑动滚动条,将滚动条滑动所到的刻度传给窗口中的Label将其显示:
import tkinter as tk
window = tk.Tk()
window.title('My Scale')
window.geometry('300x300')
l = tk.Label(window, bg = 'blue', width = 20, text = 'empty')
l.pack()
# 这里参数v是用来记录滚动条定位的数据(滑动到哪里了)
def job(v):
l.config(text = 'you have choosen ' + v)
# 参数解释:
# from_ = 1, to = 20:从1到20的意思,就是滚动条的起始刻度到终止刻度
# orient = tk.HORIZONAL是设置滚动条的方向,是纵向放,还是横向放
# length是指整个滚动条在window上的长度(以px像素为单位)
# resolution = 0.01是设置滚动条的精度,移动一步按照两位小数来计算
# showvalue = 1:表示滚动条的游标cur上方是否会显示当前选中的滑动值
# tkinterval = 4:设置滚动条下方的坐标间隔,这里按照每4个单位来计算
s = tk.Scale(window, label = 'push me', from_ = 1, to = 20, orient = tk.HORIZONTAL,
length = 200, showvalue = 1, tickinterval = 4, resolution = 0.01, command = job)
s.pack()
window.mainloop()
初始:
滑动后:
g. Tkinter中CheckButton(复选框):
我们常常会在表单中遇到如下的选择框,让您填写会哪些编程语言,下面罗列了最常用的编程语言,你点击一个框就选中了一门语言,你可以同时点击多个选择框,进行多选。所以称复选框或者多选框。我们也模仿做一个常用语言复选框,每选择一个让Label显示不同的内容:
import tkinter as tk
window = tk.Tk()
window.title('My CheckBox')
window.geometry('300x300')
l = tk.Label(window, bg = 'red', width = 20, text = 'empty')
l.pack()
# 通过判断每个复选框是否被选择来进行判断。再将Label显示内容进行替换
def job():
if (var1.get() == 1) and (var2.get() == 0) and (var3.get() == 0):
l.config(text = 'I love only C++')
elif (var1.get() == 0) and (var2.get() == 1) and (var3.get() == 0):
l.config(text = 'I love only Java')
elif (var1.get() == 0) and (var2.get() == 0) and (var3.get() == 1):
l.config(text = 'I love only Python')
elif (var1.get() == 1) and (var2.get() == 1) and (var3.get() == 0):
l.config(text = 'I love C++ and Java')
elif (var1.get() == 1) and (var2.get() == 0) and (var3.get() == 1):
l.config(text = 'I love C++ and Python')
elif (var1.get() == 0) and (var2.get() == 1) and (var3.get() == 1):
l.config(text = 'I love Java and Python')
elif (var1.get() == 1) and (var2.get() == 1) and (var3.get() == 1):
l.config(text = 'I love C++ and Java and Python')
else :
l.config(text = 'I love all lanuage')
var1 = tk.IntVar()
# 参数解释: variable:表示将var1变量绑定到cb1上
# 参数onvalue和前面讲的部件radiobutton中的value相似, 当我们选中了这个checkbutton,
# onvalue的值1就会放入到var1中, 然后var1将其赋值给参数variable,offvalue用法相似,
# 但是offvalue是在没有选中这个checkbutton时,offvalue的值1放入var1,然后赋值给参数variable
# 这是创建一个checkbutton部件,以此类推,可以创建多个checkbutton
cb1 = tk.Checkbutton(window, text = 'C++', variable = var1, onvalue = 1, offvalue = 0, command = job)
var2 = tk.IntVar()
cb2 = tk.Checkbutton(window, text = 'Java', variable = var2, onvalue = 1, offvalue = 0, command = job)
var3 = tk.IntVar()
cb3 = tk.Checkbutton(window, text = 'Python', variable = var3, onvalue = 1, offvalue = 0, command = job)
cb1.pack()
cb2.pack()
cb3.pack()
window.mainloop()
初始:
选择单个:
选择多个:
h. Tkinter的Canvas(画布):
Canvas画布部件是指的是像一块画板类似的,可以在上面嵌套图片,以及一些图形。模拟一个实例:嵌套一个图片在左上角,然后画出一些几何图形,通过点击button使得某一个图形进行移动操作:
import tkinter as tk
window = tk.Tk()
window.title('My Carvans')
window.geometry('300x200')
# 定义一个画布
canvas = tk.Canvas(window, bg='green', height=100, width=200)
# 读取一个图片,Mac系统只能读取gif后缀图片, 路径最好可以使用绝对路径,我的是放在同一个目录下
image_file = tk.PhotoImage(file='inf.gif')
# 创造一个图片变量
# 里面的参数10,10就是图片放入画布的坐标,
# 而这里的anchor=nw则是把图片的左上角作为锚定点,在加上刚刚给的坐标位置,即可将图片位置确定。
# 最后一个参数的意思大家应该都知道,就是将刚刚存入的图片变量,赋值给image。
image = canvas.create_image(10, 10, anchor='nw', image=image_file)
x0, y0, x1, y1= 50, 50, 80, 80
line = canvas.create_line(x0, y0, x1, y1) # 创建一条直线
oval = canvas.create_oval(x0, y0, x1, y1, fill='red') # 创建一个圆,填充色为红色
arc = canvas.create_arc(x0+30, y0+30, x1+30, y1+30, start=0, extent=180) # 创建一个角度从0到180的扇形
rect = canvas.create_rectangle(100, 30, 100+20, 30+20) # 创建一个矩形
canvas.pack()
# 定义每点击一次按钮正方形向下移动两个单位操作
def moveit():
canvas.move(rect, 0, 2)
b = tk.Button(window, text='move', command=moveit).pack()
window.mainloop()
初始:
点击move每次向下移动两个单位长度
i. Tkinter中的MenuBar(菜单栏):
窗口的菜单栏想必大家都见过,Mac上是固定在屏幕左上角的菜单栏,上面包括一些常用的设置和操作。
我们在Tkinter中可以使用MenuBar模仿做出类似效果的菜单栏:
import tkinter as tk
window = tk.Tk()
window.title('My MenuBar')
window.geometry('200x200')
l = tk.Label(window, text='', bg='red')
l.pack()
counter = 0
# 功能:每点击一次'New''Open''Save'就将counter+1,然后设置到Label上
def do_job():
global counter
l.config(text='do '+ str(counter))
counter+=1
# 定义一个MenuBar,在窗口上方
menubar = tk.Menu(window)
# 定义一个空的菜单栏单元
filemenu = tk.Menu(menubar, tearoff=0)
# 将定义的菜单栏单元命名为File
menubar.add_cascade(label='File', menu=filemenu)
# 给菜单栏添加小的菜单,就是我们平时窗口操作的下拉菜单,每一个小的菜单对应一个功能。
filemenu.add_command(label='New', command=do_job)
filemenu.add_command(label='Open', command=do_job)
filemenu.add_command(label='Save', command=do_job)
filemenu.add_separator() # 加一条分割线
filemenu.add_command(label='Exit', command=window.quit)
editmenu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label='Edit', menu=editmenu)
editmenu.add_command(label='Cut', command=do_job)
editmenu.add_command(label='Copy', command=do_job)
editmenu.add_command(label='Paste', command=do_job)
submenu = tk.Menu(filemenu)
filemenu.add_cascade(label='Import', menu=submenu, underline=0) # 在filemenu加入一个小菜单
submenu.add_command(label="Submenu1", command=do_job)
window.config(menu=menubar)
window.mainloop()
初始:
菜单栏:
可以点击每个小菜单查看是否实现了计数功能退出功能等操作。
j. Tkinter中Frame(框架):
Frame 是一个在 窗口上分离小区域的部件, 它能将 窗口 分成不同的区,然后存放不同的其他部件. 同时一个 Frame 上也能再分成两个 Frame, Frame 可以认为是一种容器.
我们现在将在窗口上添加一个主Frame,然后在主Frame上继续pack子Frame在它的右边或左边。
import tkinter as tk
window = tk.Tk()
window.title('My Frame')
window.geometry('200x200')
tk.Label(window, text='on the window').pack()
# 创建一个主框架
frm = tk.Frame(window)
frm.pack()
# 基于frm框架创建一个左边的子框架
frm_l = tk.Frame(frm)
# 基于frm框架创建一个右边的子框架
frm_r = tk.Frame(frm)
frm_l.pack(side='left') # pack中的side方法是将frm_l,frm_r两个子框架按照左或右的方向添加到frm上
frm_r.pack(side='right')
# 这里的三个label就是在我们创建的frame上定义的label部件,还是以容器理解,就是容器上贴了标签,
# 来指明这个是什么,解释这个容器。
tk.Label(frm_l, text='on the frm_l1').pack()
tk.Label(frm_l, text='on the frm_l2').pack()
tk.Label(frm_r, text='on the frm_r1').pack()
window.mainloop()
Result:
k. Tkinter中的MessageBox(弹窗框):
在网页中我们点击一些链接可能会出现弹窗提醒,提醒有警告提醒,错误提醒,以及通过提醒等。我们下面将用一个例子阐述Tkinter中的MessageBox中的几种弹窗:
import tkinter as tk
import tkinter.messagebox
window = tk.Tk()
window.title('My MessageBox')
window.geometry('200x200')
def job():
# tk.messagebox.showinfo(title='Hi', message='hahahaha') # return 'ok'
# tk.messagebox.showwarning(title='Hi', message='nononono') # return 'ok' 警告框
# tk.messagebox.showerror(title='Hi', message='No!! never') # return 'ok' 错误框
# print(tk.messagebox.askquestion(title='Hi', message='hahahaha')) # return 'yes' , 'no' # 验证yes or no框
print(tk.messagebox.askyesno(title='Hi', message='hahahaha')) # return True, False
# print(tk.messagebox.asktrycancel(title='Hi', message='hahahaha')) # return True, False
# print(tk.messagebox.askokcancel(title='Hi', message='hahahaha')) # return True, False
# print(tk.messagebox.askyesnocancel(title="Hi", message="haha")) # return, True, False, None
b = tk.Button(window, text = 'click me', bg = 'yellow', command = job)
b.pack()
window.mainloop()
Showinfo:
![](/Users/liyan/Library/Application Support/typora-user-images/image-20200714212513455.png)
Showwarning:
![](/Users/liyan/Library/Application Support/typora-user-images/image-20200714212736650.png)
Showerror:
Askyesno:
![](/Users/liyan/Library/Application Support/typora-user-images/image-20200714213022344.png)
l. Tkinter中的摆放组件的三种方法pack, grid, place:
import tkinter as tk
window = tk.Tk()
window.geometry('200x200')
# 使用pack(side = '')来放置组件的位置
'''
tk.Label(window, text='1').pack(side='top')
tk.Label(window, text='1').pack(side='bottom')
tk.Label(window, text='1').pack(side='left')
tk.Label(window, text='1').pack(side='right')
'''
# 使用grid进行位置摆放组件:padx:单元格左右间距 pdy:单元格上下间距
for i in range(4):
for j in range(3):
tk.Label(window, text=1).grid(row=i, column=j, padx=10, pady=10)
# 使用place进行位置摆放组件:anchor:锚点的位置nw:north west西北方向
# tk.Label(window, text=1).place(x=20, y=10, anchor='nw')
window.mainloop()
pack:
grid:
place:
到此,对于Tkinter中的一些基础操作介绍完毕了。接下来我们将使用这些知识做一个example(about login window):
创建一个登陆注册窗口,点击登陆可以校验用户名密码是否匹配进行判断,可以通过注册按钮重新弹出一个注册界面窗口,在里面进行注册,可判断两次输入密码是否一致以及用户名是否存在等操作。第一次没有任何数据文件在使用用户名和密码登录时会抛出文件不存在异常,将第一次输入的用户名密码写入一个新的 文件,这样之后注册,登陆就是读取这个创建的文件。
import tkinter as tk
import pickle
import tkinter.messagebox
window = tk.Tk()
window.title('Login & Register Window')
window.geometry('450x300')
# 创建一个画布,将图片嵌入在画布上,以左上角为原点,使用pack方法将画布置于窗口顶部
canvas = tk.Canvas(window, height = 200, width = 500)
image_file = tk.PhotoImage(file = 'welcome.gif')
image = canvas.create_image(0, 0, anchor = 'nw', image = image_file)
canvas.pack(side = 'top')
# 在window上设置两个label表示用户名和用户密码
tk.Label(window, text = 'User_name:').place(x = 50, y = 150)
tk.Label(window, text = 'User_password:').place(x = 50, y = 200)
# 设置两个输入框,用户名输入框默认设置root,然后输入框使用place在window上定位
var_name = tk.StringVar()
var_name.set('root')
entry_name = tk.Entry(window, textvariable = var_name)
entry_name.place(x = 170, y = 150)
var_pwd = tk.StringVar()
entry_pwd = tk.Entry(window, textvariable = var_pwd, show = '*')
entry_pwd.place(x = 170, y = 200)
# 定义了Login的一些操作,里面使用pyhton的pickle模块进行对文件的操作,用dict存储用户名密码
# 将dict序列化存储到data.pickle中,再判断用户名密码的时候使用pickle.load加载数据
def Login():
user_name = var_name.get()
user_pwd = var_pwd.get()
try:
with open ('data.pickle', 'rb') as f:
user_info = pickle.load(f)
except FileNotFoundError:
with open('data.pickle', 'wb') as f:
user_info = {'root': 'root'}
pickle.dump(user_info, f)
# 判断用户名是否注册,用户名对应的密码是否一致
if user_name in user_info:
if user_pwd == user_info[user_name]:
tk.messagebox.showinfo(title = 'Welcome', message = 'Welcome to ' + user_name)
else:
tk.messagebox.showerror(title = 'Error', message = 'your password is wrong, try again')
else:
is_register = tk.messagebox.askyesno('Welcome', 'You have not register yet. Register today?')
# 如果还没注册,就跳转窗口进行register
if is_register:
Register()
# 定义了Register的操作
def Register():
# 用于处理Register的窗口中注册button的功能
def register():
# 获取输入密码和确认密码,进行逻辑判断
np = new_pwd.get()
npf = new_pwd_confirm.get()
nn = new_name.get()
with open('data.pickle', 'rb') as f:
exist_usr_info = pickle.load(f)
if np != npf:
tk.messagebox.showerror('Error', 'Password and confirm password must be the same!')
elif nn in exist_usr_info:
tk.messagebox.showerror('Error', 'The user has already register!')
else:
exist_usr_info[nn] = np
with open('data.pickle', 'wb') as f:
pickle.dump(exist_usr_info, f)
tk.messagebox.showinfo('Welcome', 'You have successfully register!')
window_sign_up.destroy()
# 创建一个新的窗口用于Register使用
window_sign_up = tk.Toplevel(window)
window_sign_up.geometry('350x200')
window_sign_up.title('Register Window')
new_name = tk.StringVar()
new_name.set('root')
tk.Label(window_sign_up, text='User name: ').place(x=10, y= 10)
entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)
entry_new_name.place(x=150, y=10)
new_pwd = tk.StringVar()
tk.Label(window_sign_up, text='Password: ').place(x=10, y=50)
entry_usr_pwd = tk.Entry(window_sign_up, textvariable=new_pwd, show='*')
entry_usr_pwd.place(x=150, y=50)
new_pwd_confirm = tk.StringVar()
tk.Label(window_sign_up, text='Confirm password: ').place(x=10, y= 90)
entry_usr_pwd_confirm = tk.Entry(window_sign_up, textvariable=new_pwd_confirm, show='*')
entry_usr_pwd_confirm.place(x=150, y=90)
btn_comfirm_sign_up = tk.Button(window_sign_up, text='Register', command = register)
btn_comfirm_sign_up.place(x=150, y=130)
# 设置两个button,一个用于login,一个用于register
button_login = tk.Button(window, text = 'login', command = Login)
button_login.place(x = 170, y = 250)
button_register = tk.Button(window, text = 'register', command = Register)
button_register.place(x = 270, y = 250)
window.mainloop()
整个教程的Code:请访问code
至于Tkinter中各种组件的详细的参数可以参考:refrence
感谢Morvan老师的教程