什么是 Tkinter

简单介绍

Tkinter 是使用 python 进行窗口视窗设计的模块. 简单的构造, 多平台, 多系统的兼容性, 能让它成为让你快速入门定制窗口文件的好助手. 它在 python 窗口视窗模块中是一款简单型的. 所以用来入门, 熟悉 窗口视窗的使用, 非常有必要.

Label & Button 标签和按钮

窗口主体框架

每一个 tkinter 应用的主体框架都可以包含下面这部分. 定义 window 窗口 和 window的一些属性, 然后书写窗口内容, 最后执行window.mainloop让窗口活起来.

1
2
3
4
5
6
7
8
9
import tkinter as tk

window = tk.Tk()
window.title('my window')
window.geometry('200x100')

# 这里是窗口的内容

window.mainloop()

窗口内容

这次我们会建立一个用来描述的标签 tk.Label, 比如:

1
2
3
4
5
6
7
l = tk.Label(window, 
text='OMG! this is TK!', # 标签的文字
bg='green', # 背景颜色
font=('Arial', 12), # 字体和字体大小
width=15, height=2 # 标签长宽
)
l.pack() # 固定窗口位置

我们也可以通过变量的形式控制标签的显示, 这时我们引入按钮 tk.Button 的概念, 没点一次按钮, 标签变化一次. 用一下内容替换上面的标签. 并把需要变化的文字存成变量 var:

1
2
3
4
5
var = tk.StringVar()    # 这时文字变量储存器
l = tk.Label(window,
textvariable=var, # 使用 textvariable 替换 text, 因为这个可以变化
bg='green', font=('Arial', 12), width=15, height=2)
l.pack()

接着我们来做 按钮 tk.Button:

1
2
3
4
5
b = tk.Button(window, 
text='hit me', # 显示在按钮上的文字
width=15, height=2,
command=hit_me) # 点击按钮式执行的命令
b.pack() # 按钮位置

那么点击是的命令我们用 if else 语句来判断. 用 on_hit 来判断当前状态.

1
2
3
4
5
6
7
8
9
on_hit = False  # 默认初始状态为 False
def hit_me():
global on_hit
if on_hit == False: # 从 False 状态变成 True 状态
on_hit = True
var.set('you hit me') # 设置标签的文字为 'you hit me'
else: # 从 True 状态变成 False 状态
on_hit = False
var.set('') # 设置 文字为空

Entry & Text 输入, 文本框

窗口主体框架

每一个tkinter应用的主体框架都包含以下几部分:

  • 主窗口: window,及主窗口的一些基本属性(标题、大小)
  • 让窗口活起来:window.mainloop()
1
2
3
4
5
6
7
8
9
10
import tkinter as tk

window = tk.Tk()
window.title('my window')

##窗口尺寸
window.geometry('200x200')

##显示出来
window.mainloop()

窗口内容(窗口上的控件)

创建按钮分别触发两种情况

1
2
3
4
5
b1 = tk.Button(window,text="insert point",width=15,height=2,command=insert_point)
b1.pack()

b2 = tk.Button(window,text="insert end",command=insert_end)
b2.pack()

创建输入框entry,用户输入任何内容都显示为*

1
2
e = tk.Entry(window,show='*')
e.pack()

创建一个文本框用于显示

1
2
t = tk.Text(window,height=2)
t.pack()

定义触发事件时的函数(注意:因为Python的执行顺序是从上往下,所以函数一定要放在按钮的上面)

1
2
3
4
5
6
7
def insert_point():
var = e.get()
t.insert('insert',var)

def insert_end():
var = e.get()
t.insert('end',var)

Listbox 列表部件

创建主窗口

1
2
3
window = tk.Tk()
window.title('my window')
window.geometry('200x200')

创建一个label用于显示

1
2
3
var1 = tk.StringVar()    #创建变量
l =tk.Label(window,bg='yellow',width=4,textvariable=var1)
l.pack()

创建一个方法用于按钮的点击事件

1
2
3
def print_selection():
value = lb.get(lb.curselection()) #获取当前选中的文本
var1.set(value) #为label设置值

创建一个按钮

1
2
3
b1 = tk.Button(window, text='print selection', width=15,
height=2, command=print_selection)
b1.pack()

创建一个Listbox和变量var2,并将var2的值赋给Listbox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var2 = tk.StringVar()
var2.set((11,22,33,44)) #为变量设置值

#创建Listbox

lb = tk.Listbox(window, listvariable=var2) #将var2的值赋给Listbox

#创建一个list并将值循环添加到Listbox控件中
list_items = [1,2,3,4]
for item in list_items:
lb.insert('end', item) #从最后一个位置开始加入值
lb.insert(1, 'first') #在第一个位置加入'first'字符
lb.insert(2, 'second') #在第二个位置加入'second'字符
lb.delete(2) #删除第二个位置的字符
lb.pack()

#显示主窗口
window.mainloop()

Radiobutton 选择按钮

radiobutton 部件

首先我们需要定义一个 var 用来将 radiobutton 的值和 Label 的值联系在一起. 然后创建一个radiobutton部分:

1
2
3
4
5
6
7
8
var = tk.StringVar()
l = tk.Label(window, bg='yellow', width=20, text='empty')
l.pack()

r1 = tk.Radiobutton(window, text='Option A',
variable=var, value='A',
command=print_selection)
r1.pack()

其中variable=var, value='A'的意思就是,当我们鼠标选中了其中一个选项,把value的值A放到变量var中,然后赋值给variable

触发功能

我们将定义一个功能, 用来对选择的 radiobutton 进行操作. print_selection 功能就是选择了某个 radiobutton 后我们会在屏幕上打印的选项.

1
2
def print_selection():
l.config(text='you have selected ' + var.get())

当触发这个函数功能时,我们的 label 中就会显示 text 所赋值的字符串即 ‘you have selected’, 后面则是我们所选中的选项 var.get()就是获取到变量 var 的值, 举个例子就是我们一开始所做的将选项 “option A” 选中时的值以 “A” 放入 var 中, 所以获取的也就是A 即如果我们这时候选中 “option A” 选项,label显示的值则是 “you have selected A”.

Scale 尺度

scale 部件

1
2
3
s = tk.Scale(window, label='try me', from_=5, to=11, orient=tk.HORIZONTAL,
length=200, showvalue=0, tickinterval=2, resolution=0.01, command=print_selection)
s.pack()

这里的参数label是指scale部件的名称,即在这里scale部件名称为try me

  • 参数from_=5,to=11的意思就是从5到11,即这个滚动条最小值为5,最大值为11(这里使用from_是因为在python中有from这个关键词)
  • 参数orient=tk.HORIZONTAL在这里就是设置滚动条的方向,如我们所看到的效果图,这里HORIZONTAL就是横向。
  • 参数length这里是指滚动条部件的长度,但注意的是和其他部件width表示不同,width表示的是以字符为单位,比如width=4,就是4个字符的长度,而此处的length=200,是指我们常用的像素为单位,即长度为200个像素
  • 参数resolution=0.01这里我们可以借助数学题来理解,我们做的很多数学题都会让我们来保留几位小数,此处的0.01就是保留2位小数,即效果图中的5.00 9.00等等后面的两位小数,如果保留一位就是resolution=0.1 这里的showvalue就是设置在滚动条上方的显示。showvalue=0,上方无结果显示,如果改为showvalue=1,则显示在上面。
  • 参数tickinterval设置的就是坐标的间隔,此处为tickinterval=2,显示的即为5.00 7.00 9.00 11.00 如果改为tickinterval=3则为5.00 8.00 11.00

触发功能

1
2
3
4
5
l = tk.Label(window, bg='yellow', width=20, text='empty')
l.pack()

def print_selection(v):
l.config(text='you have selected ' + v)

这里相比前面多了参数v,这里的参数v即将滚动条定位的数据,即如效果图中最开始,定位到5.00,label中显示you have selected 5.00

Checkbutton 勾选项

Checkbutton部件

1
2
3
4
var1 = tk.IntVar()
c1 = tk.Checkbutton(window, text='Python', variable=var1, onvalue=1, offvalue=0,
command=print_selection)
c1.pack()

参数onvalue和前面讲的部件radiobutton中的value相似, 当我们选中了这个checkbutton,onvalue的值1就会放入到var1中, 然后var1将其赋值给参数variableoffvalue用法相似,但是offvalue是在没有选中这个checkbutton时,offvalue的值1放入var1,然后赋值给参数variable 这是创建一个checkbutton部件,以此类推,可以创建多个checkbutton

触发功能

1
2
3
4
5
6
7
8
9
def print_selection():
if (var1.get() == 1) & (var2.get() == 0): #如果选中第一个选项,未选中第二个选项
l.config(text='I love only Python ')
elif (var1.get() == 0) & (var2.get() == 1): #如果选中第二个选项,未选中第一个选项
l.config(text='I love only C++')
elif (var1.get() == 0) & (var2.get() == 0): #如果两个选项都未选中
l.config(text='I do not love either')
else:
l.config(text='I love both') #如果两个选项都选中

相对于前面学过的 print_selection,这一段比较长,其实功能差不多,只不过加了if...elif...else来选择控制而已即如代码注释,config在前面已经讲过就是将参数text的值显示,这里的var1.get() == 1 就是前面所说的var1获得的变量onvalue=1var1.get() == 0即是var1获得的变量offvalu=0同理var2也是如此。

Canvas 画布

Canvas部件

1
2
canvas = tk.Canvas(window, bg='blue', height=100, width=200)
canvas.pack()

这里的参数和以往学过的部件一样,所以就不再一一解释。

1
2
image_file = tk.PhotoImage(file='ins.gif')
image = canvas.create_image(10, 10, anchor='nw', image=image_file)

这里的代码主要是实现我们最终看到的在左上角的那张小图片。 image_file = tk.PhotoImage(file='ins.gif')这一句是创造一个变量存放ins.gif这张图片。 image = canvas.create_image(10, 10, anchor='nw', image=image_file)里面的参数10,10就是图片放入画布的坐标, 而这里的anchor=nw则是把图片的左上角作为锚定点,在加上刚刚给的坐标位置,即可将图片位置确定。 最后一个参数的意思大家应该都知道,就是将刚刚存入的图片变量,赋值给image

1
2
x0, y0, x1, y1= 50, 50, 80, 80
line = canvas.create_line(x0, y0, x1, y1)

这段代码主要实现的是画一条直线,后面()中给的参数就是线段两点的坐标,两点确定一条直线。此处给的就是从坐标(50,50)到(80,80)画一条直线。

1
2
3
oval = canvas.create_oval(x0, y0, x1, y1, fill='red')  #创建一个圆,填充色为`red`红色
arc = canvas.create_arc(x0+30, y0+30, x1+30, y1+30, start=0, extent=180) #创建一个扇形
rect = canvas.create_rectangle(100, 30, 100+20, 30+20) #创建一个矩形

这里面就是创建扇形时多了两个没见过的参数start=0extent=180,其实就是从0度到180度,就好像扇子的边打开一样。在我们看来就是个半圆, 如果改为extent=90,我们看到的就是一个1/4圆

触发功能

1
2
def moveit():
canvas.move(rect, 0, 2)

这里的触发不再是以往的print_selection了,哈哈,那么这里的是怎么样的功能呢,首先我们从单词理解来看就是移动的函数,在视频中也演示过了, 就是我们每点一次button 矩形就会移动这里canvas.move(rect, 0, 2)的参数(rect,0,2)就是移动rect这个变量,即我们看到的矩形 后面的0和2,也就是横坐标移动0个单位,纵坐标移动2个单位,简单的说就是每次点击,横向不动,纵向移动两个单位。

Menubar 菜单

下面是我们制作整个菜单栏的流程, 我们先需要加入一个 Menubar 作为整体框架, 然后再在 Menubar 中加一些部件.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
##创建一个菜单栏,这里我们可以把他理解成一个容器,在窗口的上方
menubar = tk.Menu(window)

##定义一个空菜单单元
filemenu = tk.Menu(menubar, tearoff=0)

##将上面定义的空菜单命名为`File`,放在菜单栏中,就是装入那个容器中
menubar.add_cascade(label='File', menu=filemenu)

##在`File`中加入`New`的小菜单,即我们平时看到的下拉菜单,每一个小菜单对应命令操作。
##如果点击这些单元, 就会触发`do_job`的功能
filemenu.add_command(label='New', command=do_job)
filemenu.add_command(label='Open', command=do_job)##同样的在`File`中加入`Open`小菜单
filemenu.add_command(label='Save', command=do_job)##同样的在`File`中加入`Save`小菜单

filemenu.add_separator()##这里就是一条分割线

##同样的在`File`中加入`Exit`小菜单,此处对应命令为`window.quit`
filemenu.add_command(label='Exit', command=window.quit)

同样的我们在定义另一个菜单Edit也是如此和定义的File菜单一样 这里再来看一下效果中比较不一样的菜单就是File中的Import菜单, 在这个菜单选项中, 我们还能分支出更多的选项.

1
2
3
submenu = tk.Menu(filemenu)##和上面定义菜单一样,不过此处实在`File`上创建一个空的菜单
filemenu.add_cascade(label='Import', menu=submenu, underline=0)##给放入的菜单`submenu`命名为`Import`
submenu.add_command(label="Submenu1", command=do_job)##这里和上面也一样,在`Import`中加入一个小菜单命令`Submenu1`

触发功能

1
2
3
4
5
counter = 0
def do_job():
global counter
l.config(text='do '+ str(counter))
counter+=1

这里的功能就是每触发一次命令,counter就会+1,在label上的显示就会从 do 0 ,do 1 , do 2…

Frame 框架

Frame 部件

Frame 是一个在 Windows 上分离小区域的部件, 它能将 Windows 分成不同的区,然后存放不同的其他部件. 同时一个 Frame 上也能再分成两个 Frame, Frame 可以认为是一种容器.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
###定义一个`label`显示`on the window`
tk.Label(window, text='on the window').pack()

###在`window`上创建一个`frame`
frm = tk.Frame(window)
frm.pack()

###在刚刚创建的`frame`上创建两个`frame`,我们可以把它理解成一个大容器里套了一个小容器,即`frm`上有两个`frame` ,`frm_l`和`frm_r`

frm_l = tk.Frame(frm)
frm_r = tk.Frame(frm)

###这里是控制小的`frm`部件在大的`frm`的相对位置,此处`frm_l`就是在`frm`的左边,`frm_r`在`frm`的右边
frm_l.pack(side='left')
frm_r.pack(side='right')

###这里的三个label就是在我们创建的frame上定义的label部件,还是以容器理解,就是容器上贴了标签,来指明这个是什么,解释这个容器。
tk.Label(frm_l, text='on the frm_l1').pack()##这个`label`长在`frm_l`上,显示为`on the frm_l1`
tk.Label(frm_l, text='on the frm_l2').pack()##这个`label`长在`frm_l`上,显示为`on the frm_l2`
tk.Label(frm_r, text='on the frm_r1').pack()##这个`label`长在`frm_r`上,显示为`on the frm_r1`

messagebox 弹窗

messagebox部件

其实这里的messagebox就是我们平时看到的弹窗。 我们首先需要定义一个触发功能,来触发这个弹窗 这里我们就放上以前学过的button按钮

1
tk.Button(window, text='hit me', command=hit_me).pack()

通过触发功能,调用messagebox

1
2
def hit_me():
tk.messagebox.showinfo(title='Hi', message='hahahaha')

这里点击button按钮就会弹出提示对话窗

下面给出几种形式

1
2
3
4
tk.messagebox.showinfo(title='',message='')#提示信息对话窗
tk.messagebox.showwarning()#提出警告对话窗
tk.messagebox.showerror()#提出错误对话窗
tk.messagebox.askquestion()#询问选择对话窗

如果给出如下定义就是打印出我们所选项对应的值

1
2
def hit_me():
print(tk.messagebox.askquestion(title='Hi', message='hahahaha'))

同样创建方法都是一样的形式

1
2
3
4
print(tk.messagebox.askquestion())#返回yes和no
print(tk.messagebox.askokcancel())#返回true和false
print(tk.messagebox.askyesno())#返回true和false
print(tk.messagebox.askretrycancel())#返回true和false

pack grid place 放置位置

pack

首先我们先看看我们常用的pack(), 他会按照上下左右的方式排列.

1
2
3
4
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

接下里我们在看看grid(), grid 是方格, 所以所有的内容会被放在这些规律的方格中.

1
2
3
for i in range(4):
for j in range(3):
tk.Label(window, text=1).grid(row=i, column=j, padx=10, pady=10)

以上的代码就是创建一个四行三列的表格,其实grid就是用表格的形式定位的。这里的参数 row为行,colum为列,padx就是单元格左右间距,pady就是单元格上下间距。

place

再接下来就是place(), 这个比较容易理解,就是给精确的坐标来定位,如此处给的(20,10),就是将这个部件放在坐标为(x,y)的这个位置 后面的参数anchor=nw就是前面所讲的锚定点是西北角。

1
tk.Label(window, text=1).place(x=20, y=10, anchor='nw')
案例: 登录窗口

1.界面创建

1
2
3
4
5
# welcome image
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')#放置画布(为上端)

这里创建的就是我们效果图中的welcome, 如果你想使用和我一样的 welcome 的图片, 你可以在这里下载。

1
2
3
4
5
6
7
8
9
10
11
# user information
tk.Label(window, text='User name: ').place(x=50, y= 150)#创建一个`label`名为`User name: `置于坐标(50,150)
tk.Label(window, text='Password: ').place(x=50, y= 190)

var_usr_name = tk.StringVar()#定义变量
var_usr_name.set('example@python.com')#变量赋值'example@python.com'
entry_usr_name = tk.Entry(window, textvariable=var_usr_name)#创建一个`entry`,显示为变量`var_usr_name`即图中的`example@python.com`
entry_usr_name.place(x=160, y=150)
var_usr_pwd = tk.StringVar()
entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, show='*')#`show`这个参数将输入的密码变为`***`的形式
entry_usr_pwd.place(x=160, y=190)

这里就是创建我们熟悉的登录界面,就是常见的用户名,密码。

1
2
3
4
5
# login and sign up button
btn_login = tk.Button(window, text='Login', command=usr_login)#定义一个`button`按钮,名为`Login`,触发命令为`usr_login`
btn_login.place(x=170, y=230)
btn_sign_up = tk.Button(window, text='Sign up', command=usr_sign_up)
btn_sign_up.place(x=270, y=230)

这里定义的就是我们的登录按钮。

2.触发功能

1
2
3
4
def usr_login():
pass
def usr_sign_up():
pass

3.触发的 usr_login 功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
##这两行代码就是获取用户输入的`usr_name`和`usr_pwd`
usr_name = var_usr_name.get()
usr_pwd = var_usr_pwd.get()

##这里设置异常捕获,当我们第一次访问用户信息文件时是不存在的,所以这里设置异常捕获。
##中间的两行就是我们的匹配,即程序将输入的信息和文件中的信息匹配。
try:
with open('usrs_info.pickle', 'rb') as usr_file:
usrs_info = pickle.load(usr_file)
except FileNotFoundError:
##这里就是我们在没有读取到`usr_file`的时候,程序会创建一个`usr_file`这个文件,并将管理员
##的用户和密码写入,即用户名为`admin`密码为`admin`。
with open('usrs_info.pickle', 'wb') as usr_file:
usrs_info = {'admin': 'admin'}
pickle.dump(usrs_info, usr_file)

这一部分就是将用户输入的用户名和密码获取到,和我们保存在usr_file中的数据对比。针对正确的密码和错误的密码分别对待.

1
2
3
4
5
6
7
8
9
10
11
12
13
#如果用户名和密码与文件中的匹配成功,则会登录成功,并跳出弹窗`how are you?`加上你的用户名。
if usr_name in usrs_info:
if usr_pwd == usrs_info[usr_name]:
tk.messagebox.showinfo(title='Welcome', message='How are you? ' + usr_name)
##如果用户名匹配成功,而密码输入错误,则会弹出'Error, your password is wrong, try again.'
else:
tk.messagebox.showerror(message='Error, your password is wrong, try again.')
else: # 如果发现用户名不存在
is_sign_up = tk.messagebox.askyesno('Welcome',
'You have not sign up yet. Sign up today?')
# 提示需不需要注册新用户
if is_sign_up:
usr_sign_up()

4.usr_sign_up 界面

1
2
3
window_sign_up = tk.Toplevel(window)
window_sign_up.geometry('350x200')
window_sign_up.title('Sign up window')

这一段首先是创建一个注册的窗口。这里和以往不同的是,多了一个tk.Toplevel我们打个比方,就好像我们前面所学 的frame一样,就是在编辑的功能下还有很多功能一样,这里就是在主体窗口的window上创建一个Sign up window窗口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
new_name = tk.StringVar()#将输入的注册名赋值给变量
new_name.set('example@python.com')#将最初显示定为'example@python.com'
tk.Label(window_sign_up, text='User name: ').place(x=10, y= 10)#将`User name:`放置在坐标(10,10)。
entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)#创建一个注册名的`entry`,变量为`new_name`
entry_new_name.place(x=150, y=10)#`entry`放置在坐标(150,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)

# 下面的 sign_to_Mofan_Python 我们再后面接着说
btn_comfirm_sign_up = tk.Button(window_sign_up, text='Sign up', command=sign_to_Mofan_Python)
btn_comfirm_sign_up.place(x=150, y=130)

相信大家对这一段代码已经很熟悉了,因为这是大家前面所学过的知识。其实就是像我们平时所见的注册窗口有一样,在Sign up window窗口 上添加new_namenew_pwdnew_pwd_confirm,还有最后一个注册按钮。这里便于大家复习,我们将new_name这段详细介绍一下(如代码注释)。 到这里就完成了我们这个注册的主要界面用户名,密码,确认密码。

5.sign_to_Mofan_Python() 功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def usr_sign_up():
def sign_to_Mofan_Python():
##以下三行就是获取我们注册时所输入的信息
np = new_pwd.get()
npf = new_pwd_confirm.get()
nn = new_name.get()

##这里是打开我们记录数据的文件,将注册信息读出
with open('usrs_info.pickle', 'rb') as usr_file:
exist_usr_info = pickle.load(usr_file)

##这里就是判断,如果两次密码输入不一致,则提示`'Error', 'Password and confirm password must be the same!'`
if np != npf:
tk.messagebox.showerror('Error', 'Password and confirm password must be the same!')

##如果用户名已经在我们的数据文件中,则提示`'Error', 'The user has already signed up!'`
elif nn in exist_usr_info:
tk.messagebox.showerror('Error', 'The user has already signed up!')

##最后如果输入无以上错误,则将注册输入的信息记录到文件当中,并提示注册成功`'Welcome', 'You have successfully signed up!'`
##然后销毁窗口。
else:
exist_usr_info[nn] = np
with open('usrs_info.pickle', 'wb') as usr_file:
pickle.dump(exist_usr_info, usr_file)
tk.messagebox.showinfo('Welcome', 'You have successfully signed up!')
##然后销毁窗口。
window_sign_up.destroy()

这里其实和前面所讲的login功能类似,如代码注释。

如果两次密码输入不一致,则提示'Error', 'Password and confirm password must be the same!'

如果用户名已经在我们的数据文件中,则提示'Error', 'The user has already signed up!'

注册成功就是我们一开始展示的效果图。

更多代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
from tkinter import *

root = Tk()
# root.title('我的第一个Python窗体')
# root.geometry('240x240') # 这里的乘号不是 * ,而是小写英文字母 x

# lb = Label(root, text='我是第一个标签',
# bg='#d3fbfb',
# fg='red',
# font=('华文新魏', 32),
# width=20,
# height=2,
# relief=SUNKEN)
# lb.pack()

# root.geometry('320x240')
# msg1 = Message(root, text='''我的水平起始位置相对窗体 0.2,垂直起始位置为绝对位置 80 像素,我的高度是窗体高度的0.4,宽度是200像素''', relief=GROOVE)
# msg1.place(relx=0.2, y=80, relheight=0.4, width=200)

root.mainloop()
'''
# 时钟
# 方法一:利用configure()方法或config()来实现文本变化
import tkinter
import time


def gettime():
timestr = time.strftime("%H:%M:%S") # 获取当前的时间并转化为字符串
lb.configure(text=timestr) # 重新设置标签文本
root.after(1000, gettime) # 每隔1s调用函数 gettime 自身获取时间


root = tkinter.Tk()
root.title('时钟')

lb = tkinter.Label(root, text='', fg='blue', font=("黑体", 80))
lb.pack()
gettime()
root.mainloop()
'''

'''# 方法二:利用textvariable变量属性来实现文本变化

import tkinter
import time


def gettime():
var.set(time.strftime("%H:%M:%S")) # 获取当前时间
root.after(1000, gettime) # 每隔1s调用函数 gettime 自身获取时间


root = tkinter.Tk()
root.title('时钟')
var = tkinter.StringVar()

lb = tkinter.Label(root, textvariable=var, fg='blue', font=("黑体", 80))
lb.pack()
gettime()
root.mainloop()'''

'''from tkinter import *
import time
import datetime


def gettime():
s = str(datetime.datetime.now()) + '\n'
txt.insert(END, s)
root.after(1000, gettime) # 每隔1s调用函数 gettime 自身获取时间


root = Tk()
root.geometry('320x240')
txt = Text(root)
txt.pack()
gettime()
root.mainloop()'''

'''from tkinter import *


def run1():
a = float(inp1.get())
b = float(inp2.get())
s = '%0.2f+%0.2f=%0.2f\n' % (a, b, a + b)
txt.insert(END, s) # 追加显示运算结果
inp1.delete(0, END) # 清空输入
inp2.delete(0, END) # 清空输入


def run2(x, y):
a = float(x)
b = float(y)
s = '%0.2f+%0.2f=%0.2f\n' % (a, b, a + b)
txt.insert(END, s) # 追加显示运算结果
inp1.delete(0, END) # 清空输入
inp2.delete(0, END) # 清空输入


root = Tk()
root.geometry('460x240')
root.title('简单加法器')

lb1 = Label(root, text='请输入两个数,按下面两个按钮之一进行加法计算')
lb1.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.1)
inp1 = Entry(root)
inp1.place(relx=0.1, rely=0.2, relwidth=0.3, relheight=0.1)
inp2 = Entry(root)
inp2.place(relx=0.6, rely=0.2, relwidth=0.3, relheight=0.1)

# 方法-直接调用 run1()
btn1 = Button(root, text='方法一', command=run1)
btn1.place(relx=0.1, rely=0.4, relwidth=0.3, relheight=0.1)

# 方法二利用 lambda 传参数调用run2()
btn2 = Button(root, text='方法二', command=lambda: run2(inp1.get(), inp2.get()))
btn2.place(relx=0.6, rely=0.4, relwidth=0.3, relheight=0.1)

# 在窗体垂直自上而下位置60%处起,布局相对窗体高度40%高的文本框
txt = Text(root)
txt.place(rely=0.6, relheight=0.4)

root.mainloop()
'''

'''# 单选框
from tkinter import *


def Mysel():
dic = {0: '甲', 1: '乙', 2: '丙'}
s = "您选了" + dic.get(var.get()) + "项"
lb.config(text=s)


root = Tk()
root.title('单选按钮')
lb = Label(root)
lb.pack()

var = IntVar()
rd1 = Radiobutton(root, text="甲", variable=var, value=0, command=Mysel)
rd1.pack()

rd2 = Radiobutton(root, text="乙", variable=var, value=1, command=Mysel)
rd2.pack()

rd3 = Radiobutton(root, text="丙", variable=var, value=2, command=Mysel)
rd3.pack()

root.mainloop()
'''

'''# 复选框
from tkinter import *
import tkinter


def run():
if (CheckVar1.get() == 0 and CheckVar2.get() == 0 and CheckVar3.get() == 0 and CheckVar4.get() == 0):
s = '您还没选择任何爱好项目'
else:
s1 = "足球" if CheckVar1.get() == 1 else ""
s2 = "篮球" if CheckVar2.get() == 1 else ""
s3 = "游泳" if CheckVar3.get() == 1 else ""
s4 = "田径" if CheckVar4.get() == 1 else ""
s = "您选择了%s %s %s %s" % (s1, s2, s3, s4)
lb2.config(text=s)


root = tkinter.Tk()
root.title('复选框')
lb1 = Label(root, text='请选择您的爱好项目')
lb1.pack()

CheckVar1 = IntVar()
CheckVar2 = IntVar()
CheckVar3 = IntVar()
CheckVar4 = IntVar()

ch1 = Checkbutton(root, text='足球', variable=CheckVar1, onvalue=1, offvalue=0)
ch2 = Checkbutton(root, text='篮球', variable=CheckVar2, onvalue=1, offvalue=0)
ch3 = Checkbutton(root, text='游泳', variable=CheckVar3, onvalue=1, offvalue=0)
ch4 = Checkbutton(root, text='田径', variable=CheckVar4, onvalue=1, offvalue=0)

ch1.pack()
ch2.pack()
ch3.pack()
ch4.pack()

btn = Button(root, text="OK", command=run)
btn.pack()

lb2 = Label(root, text='')
lb2.pack()
root.mainloop()'''

'''# 列表框
from tkinter import *


def ini():
Lstbox1.delete(0, END)
list_items = ["数学", "物理", "化学", "语文", "外语"]
for item in list_items:
Lstbox1.insert(END, item)


def clear():
Lstbox1.delete(0, END)


def ins():
if entry.get() != '':
if Lstbox1.curselection() == ():
Lstbox1.insert(Lstbox1.size(), entry.get())
else:
Lstbox1.insert(Lstbox1.curselection(), entry.get())


def updt():
if entry.get() != '' and Lstbox1.curselection() != ():
selected = Lstbox1.curselection()[0]
Lstbox1.delete(selected)
Lstbox1.insert(selected, entry.get())


def delt():
if Lstbox1.curselection() != ():
Lstbox1.delete(Lstbox1.curselection())


root = Tk()
root.title('列表框实验')
root.geometry('320x240')

frame1 = Frame(root, relief=RAISED)
frame1.place(relx=0.0)

frame2 = Frame(root, relief=GROOVE)
frame2.place(relx=0.5)

Lstbox1 = Listbox(frame1)
Lstbox1.pack()

entry = Entry(frame2)
entry.pack()

btn1 = Button(frame2, text='初始化', command=ini)
btn1.pack(fill=X)

btn2 = Button(frame2, text='添加', command=ins)
btn2.pack(fill=X)

btn3 = Button(frame2, text='插入', command=ins) # 添加和插入功能实质上是一样的
btn3.pack(fill=X)

btn4 = Button(frame2, text='修改', command=updt)
btn4.pack(fill=X)

btn5 = Button(frame2, text='删除', command=delt)
btn5.pack(fill=X)

btn6 = Button(frame2, text='清空', command=clear)
btn6.pack(fill=X)

root.mainloop()'''

'''# 组合框
from tkinter.ttk import *
from tkinter import *


def calc(event):
a = float(t1.get())
b = float(t2.get())
dic = {0: a + b, 1: a - b, 2: a * b, 3: a / b}
c = dic[comb.current()]
lbl.config(text=str(c))


root = Tk()
root.title('四则运算')
root.geometry('320x240')

t1 = Entry(root)
t1.place(relx=0.1, rely=0.1, relwidth=0.2, relheight=0.1)

t2 = Entry(root)
t2.place(relx=0.5, rely=0.1, relwidth=0.2, relheight=0.1)

var = StringVar()

comb = Combobox(root, textvariable=var, values=['加', '减', '乘', '除', ])
comb.place(relx=0.1, rely=0.5, relwidth=0.2)
comb.bind('<<ComboboxSelected>>', calc)

lbl = Label(root, text='结果')
lbl.place(relx=0.5, rely=0.7, relwidth=0.2, relheight=0.3)

root.mainloop()'''

'''# 滑块
from tkinter import *


def show(event):
s = '滑块的取值为' + str(var.get())
lb.config(text=s)


root = Tk()
root.title('滑块实验')
root.geometry('320x180')
var = DoubleVar()
scl = Scale(root, orient=HORIZONTAL, length=200, from_=1.0, to=5.0, label='请拖动滑块', tickinterval=1, resolution=0.05,
variable=var)
scl.bind('<ButtonRelease-1>', show)
scl.pack()

lb = Label(root, text='')
lb.pack()

root.mainloop()'''

'''# 菜单
from tkinter import *


def new():
s = '新建'
lb1.config(text=s)


def ope():
s = '打开'
lb1.config(text=s)


def sav():
s = '保存'
lb1.config(text=s)


def cut():
s = '剪切'
lb1.config(text=s)


def cop():
s = '复制'
lb1.config(text=s)


def pas():
s = '粘贴'
lb1.config(text=s)


def popupmenu(event):
mainmenu.post(event.x_root, event.y_root)


root = Tk()
root.title('菜单实验')
root.geometry('320x240')

lb1 = Label(root, text='显示信息', font=('黑体', 32, 'bold'))
lb1.place(relx=0.2, rely=0.2)

mainmenu = Menu(root)
menuFile = Menu(mainmenu) # 菜单分组 menuFile
mainmenu.add_cascade(label="文件", menu=menuFile)
menuFile.add_command(label="新建", command=new)
menuFile.add_command(label="打开", command=ope)
menuFile.add_command(label="保存", command=sav)
menuFile.add_separator() # 分割线
menuFile.add_command(label="退出", command=root.destroy)

menuEdit = Menu(mainmenu) # 菜单分组 menuEdit
mainmenu.add_cascade(label="编辑", menu=menuEdit)
menuEdit.add_command(label="剪切", command=cut)
menuEdit.add_command(label="复制", command=cop())
menuEdit.add_command(label="粘贴", command=pas())

root.config(menu=mainmenu)
root.bind('Button-3', popupmenu) # 根窗体绑定鼠标右击响应事件
root.mainloop()
'''

'''# 子窗体
from tkinter import *


def newwind():
winNew = Toplevel(root)
winNew.geometry('320x240')
winNew.title('新窗体')
lb2 = Label(winNew, text='我在新窗体上')
lb2.place(relx=0.2, rely=0.2)
btClose = Button(winNew, text='关闭', command=winNew.destroy)
btClose.place(relx=0.7, rely=0.5)


root = Tk()
root.title('新建窗体实验')
root.geometry('320x240')

lb1 = Label(root, text='主窗体', font=('黑体', 32, 'bold'))
lb1.place(relx=0.2, rely=0.2)

mainmenu = Menu(root)
menuFile = Menu(mainmenu)
mainmenu.add_cascade(label='菜单', menu=menuFile)
menuFile.add_command(label='新窗体', command=newwind)
menuFile.add_separator()
menuFile.add_command(label='退出', command=root.destroy)

root.config(menu=mainmenu)
root.mainloop()'''

'''# 交互对话框
from tkinter import *
import tkinter.messagebox


def xz():
answer = tkinter.messagebox.askokcancel('请选择', '请选择确定或取消')
if answer:
lb.config(text='已确认')
else:
lb.config(text='已取消')


root = Tk()

lb = Label(root, text='')
lb.pack()
btn = Button(root, text='弹出对话框', command=xz)
btn.pack()
root.mainloop()'''

'''# 输入对话框
from tkinter.simpledialog import *


def xz():
s = askstring('请输入', '请输入一串文字')
lb.config(text=s)


root = Tk()

lb = Label(root, text='')
lb.pack()
btn = Button(root, text='弹出输入对话框', command=xz)
btn.pack()
root.mainloop()
'''

'''# 文件选择对话框
from tkinter import *
import tkinter.filedialog


def xz():
filename = tkinter.filedialog.askopenfilename()
if filename != '':
lb.config(text='您选择的文件是' + filename)
else:
lb.config(text='您没有选择任何文件')


root = Tk()

lb = Label(root, text='')
lb.pack()
btn = Button(root, text='弹出文件选择对话框', command=xz)
btn.pack()
root.mainloop()'''

'''# 颜色选择对话框
from tkinter import *
import tkinter.colorchooser


def xz():
color = tkinter.colorchooser.askcolor()
colorstr = str(color)
print('打印字符串%s 切掉后=%s' % (colorstr, colorstr[-9:-2]))
lb.config(text=colorstr[-9:-2], background=colorstr[-9:-2])


root = Tk()

lb = Label(root, text='请关注颜色的变化')
lb.pack()
btn = Button(root, text='弹出颜色选择对话框', command=xz)
btn.pack()
root.mainloop()
'''

# 背景图片
'''# 插入文件图片
import tkinter as tk

root = tk.Tk()

# 创建一个标签类, [justify]:对齐方式
textLabel = tk.Label(root, text="右边会看到一个图片\n",
justify=tk.LEFT) # 左对齐
textLabel.pack(side=tk.LEFT) # 自动对齐,side:方位

# 创建一个图片管理类
photo = tk.PhotoImage(file="shop.png") # file:t图片路径
imgLabel = tk.Label(root, image=photo) # 把图片整合到标签类中
imgLabel.pack(side=tk.RIGHT) # 自动对齐

tk.mainloop()'''

'''import tkinter as tk

root = tk.Tk()

# 增加背景图片
photo = tk.PhotoImage(file="shop.png")
theLabel = tk.Label(root,
text="我是内容,\n请你阅读",
# 内容
justify=tk.LEFT,
# 对齐方式
image=photo,
# 加入图片
compound=tk.CENTER,
# 关键:设置为背景图片
font=("华文行楷", 20),
# 字体和字号
fg="white") # 前景色
theLabel.pack()

tk.mainloop()'''

'''# 插入文件图片
import tkinter as tk

root = tk.Tk()

frame1 = tk.Frame(root) # 这是上面的框架
frame2 = tk.Frame(root) # 这是下面的框架

var = tk.StringVar() # 储存文字的类
var.set("右边会看到一个图片,\n换行") # 设置文字

# 创建一个标签类, [justify]:对齐方式,[frame]所属框架
textLabel = tk.Label(frame1, textvariable=var,
justify=tk.LEFT) # 显示文字内容
textLabel.pack(side=tk.LEFT) # 自动对齐,side:方位

# 创建一个图片管理类
photo = tk.PhotoImage(file="shop.png") # file:t图片路径
imgLabel = tk.Label(frame1, image=photo) # 把图片整合到标签类中
imgLabel.pack(side=tk.RIGHT) # 自动对齐


def callback(): # 触发的函数
var.set("设置文字") # 设置文字


# [frame]所属框架 ,text 文字内容 command:触发方法
theButton = tk.Button(frame2, text="我是下面的按钮", command=callback)
theButton.pack() # 自动对齐

frame1.pack(padx=10, pady=10) # 上框架对齐
frame2.pack(padx=10, pady=10) # 下框架对齐

tk.mainloop()
'''

'''# 摄像头
from tkinter import *
import cv2
from PIL import Image, ImageTk


def take_snapshot():
print("有人给你点赞啦!")


def video_loop():
success, img = camera.read() # 从摄像头读取照片
if success:
cv2.waitKey(100)
cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA) # 转换颜色从BGR到RGBA
current_image = Image.fromarray(cv2image) # 将图像转换成Image对象
imgtk = ImageTk.PhotoImage(image=current_image)
panel.imgtk1 = imgtk
panel.config(image=imgtk)
root.after(1, video_loop)


camera = cv2.VideoCapture(0) # 摄像头

root = Tk()
root.title("opencv + tkinter")
# root.protocol('WM_DELETE_WINDOW', detector)


panel = Label(root) # initialize image panel
panel.pack(padx=10, pady=10)
# root.config(cursor="arrow")
btn = Button(root, text="点赞!", command=take_snapshot)
btn.pack(fill="both", expand=True, padx=10, pady=10)

video_loop()

root.mainloop()
# 当一切都完成后,关闭摄像头并释放所占资源
camera.release()
cv2.destroyAllWindows()
'''