GUI的终极选择:Tkinter4:Entry输入框组件
##Entry
※Entry:Entry 组件通常用于获取用户的输入文本。
(输入框是跟程序打交道的一个途径,比如说程序要求你输入账号和密码,那么他就需要提供两个输入框给你,并且接收密码的输入框还需要用 星号 * 将实际的内容给隐藏起来。
学了前面几个组件,可以发现tkinter 的组件很多方法和选项(参数)他们之间都是通用的,就是说他们名字一样,内容也差不多,比如说,在输入框中,用代码增加和删除内容,也就是使用 insert() 和 delete() 方法。)
from tkinter import *
root = Tk()
e = Entry(root)
e.pack(padx = 20,pady = 20)
mainloop()
(解析:同样,先来个root顶层窗口,然后实例化Entry组件,参数表示放到root窗口,然后赋值给变量e,然后e.pack()把它放出来,不想把输入框和边框连在一起,所以设置一下内边距
然后这个输入框可以输入中文英文字母,数字,特殊符号都可以,如果说这个输入框的容量不足以容纳这些文字的话,他会自动滚动)
※可以使用delete(0, END) 来清空输入框的内容,也可以使用insert(0, “…”)方法来设置文本框默认的内容
from tkinter import *
root = Tk()
e = Entry(root)
e.pack(padx = 20,pady = 20)
e.delete(0,END)
e.insert(0,"默认文本...")
mainloop()
※可以使用 Entry 组件的 get() 方法获取输入框中的内容
(你也可以将一个tkinter的变量(通常是字符串的变量:StringVar())挂钩到textvariable 这个选项,然后通过变量的get方法来获取也是也可以的)下面通过一个例子来演示
需求:当按下获取信息的按钮时,会清空输入框,然后把信息给打印出来
分析:从第一张图可以分析出需要在一个窗口上添加作品、作者两个Label,两个Entry以及获取信息、退出两个button按钮
第一:生成两个Label分别显示作品和作者
第二:使用 grid()网格来布局
(通常的做法,已经学过的会用两个frame把它包含起来,现在用一个新的方法,Tkinter一共提供了三种布局组件的方式,第一种就是我们熟悉的pack(),然后还有一种就是(网格)grid(),就是用表格的形式来管理你的组件,还有一种place后边讲,这次就使用grid来布局组件)
from tkinter import *
root = Tk()
Label(root,text="作品").grid(row=0,column=0)
Label(root,text="作者").grid(row=1,column=0)
e1 = Entry(root)
e2 = Entry(root)
e1.grid(row=0,column=1,padx=10,pady=5)
e2.grid(row=1,column=1,padx=10,pady=5)
def show():
print("作品:《%s》" %e1.get())
print("作者:%s" %e2.get())
e1.delete(0, "end")
e2.delete(0, "end")
Button(root,text = "获取信息",width = 10,command = show)\
.grid(row = 3,column = 0,sticky = W,padx =10,pady =5)
Button(root,text = "退出", width = 10,command = root.quit)\
.grid(row = 3,column = 1,sticky = E,padx =10,pady =5)
mainloop()
(代码解析:首先就是先来两个Label标签,分别是作品和作者,然后,刚刚说了这次使用(网格)grid()来布局组件,grid的话他是允许用表格的形式来管理组件的位置,他的选项有row和column分别代表的是行和列,作品这个组件的位置就是在0行0列,作者的位置就是在0行0列,如上图的分布
接着是两个输入框,都是放在root窗口,再使用grid来布局,这两个输入框组件,上图可以看到,他们是位置分别就是0行1列和1行1列,然后再通过padx和pady设置一下内边距,好看一些
接着是要添加两个按钮,首先是第一个按钮是获取信息,然后给他设置一下宽度,在设置一个command选项,当按钮点下时就去执行show方法,那么show方法就是输入框对象e1和e2通过get方法获取到文本框的内容,然后输出,输出完后在用delete方法情况输入框,然后退出的按钮的command就设置root.quit就可以了,即调用根方法的quit方法,
接着就是把这两个按钮摆放好,即分别是2行0列和2行1列,但是要求一个按钮偏左边,一个靠右边,这里就需要设置一个sticky的属性,sticky就是控制组件在 grid 分配的空间中的位置,他的值和之前的anchor很相似,同样使用"n", “e”, “s”, “w” 以及它们的组合来定位(ewsn代表东西南北,上北下南左西右东),然后在设置一下padx和pady他就不会挨着墙角了)
※运行成功后点击退出是没反应的,退不来,因为我们使用的 IDLE 也是使用 tkinter 写出来的,他们这里会发生冲突,双击你源文件打开,用系统cmd窗口来运行就可以正常退出,如果想在IDLE可以退出,可以使用root.destroy
※接着可以设置一个 show 选项来设计密码输入框
from tkinter import *
root = Tk()
Label(root,text="账号:").grid(row=0,column=0)
Label(root,text="密码:").grid(row=1,column=0)
v1 = StringVar()
v2 = StringVar()
e1 = Entry(root,textvariable = v1)
e2 = Entry(root,textvariable = v2,show ="*")
e1.grid(row=0,column=1,padx=10,pady=5)
e2.grid(row=1,column=1,padx=10,pady=5)
def show():
print("账号:%s" %e1.get())
print("密码:%s" %e2.get())
e1.delete(0, "end")
Button(root,text = "芝麻开门",width = 10,command = show)\
.grid(row = 3,column = 0,sticky = W,padx =10,pady =5)
Button(root,text = "退出", width = 10,command = root.destroy)\
.grid(row = 3,column = 1,sticky = E,padx =10,pady =5)
mainloop()
(解析:这里就是把上面一个例题的一些按钮改了,然后加了两个变量,因为这里需要两个变量存放账号和密码,输入框里边输入的是字符串,所以就是用Tkinter的StringVar来存放,然后Entry按钮里边就要设置textvarible属性,后边show方法要通过get方法获取输出,当然你不用加这两个变量也可以,加了就是使用前面提到的第二种获取文本框内容的方法,接着第二个输入框需要用*来显示,就直接用show ="*"就可以了,你想显示什么就传什么,也可以传show = “$”)
※接着来设计一个计算器
(计算器不能够输入除了数字之外的任何字符,但是没关系,Entry 本身就自带了 验证功能,就是验证输入框里的内容的合法性比如要求输入数字,你输入了字母那就是非法。实现该功能,需要通过设置 validate、validatecommand 和 invalidcommand 选项。)
※首先启用验证的“开关”是 validate 选项,该选项可以设置的值有:
值 | 含义 |
'focus' | 当 Entry 组件获得或失去焦点的时候验证 |
'focusin' | 当 Entry 组件获得焦点的时候验证 |
'focusout' | 当 Entry 组件失去焦点的时候验证 |
'key' | 当输入框被编辑的时候验证 |
'all' | 当出现上边任何一种情况的时候验证 |
'none' | 1. 关闭验证功能 2. 默认设置该选项(即不启用验证) 3. 注意,是字符串的 'none',而非 None |
(上面是他可以设置的值有哪些,表示在什么情况下去验证,去调用验证函数,而验证函数是在validatecommand里边指定的,跟button里边的command选项是一样的道理,validatecommand函数只能返回 True 或 False 表示验证的结果。一般情况下验证函数只需要知道输入框的内容即可,可以通过 Entry 组件的 get() 方法获得该字符串。)
下边的例子中,在第一个输入框输入“老甲鱼”,并通过 Tab 键将焦点转移到第二个输入框的时候,验证功能被成功触发:
from tkinter import *
master = Tk()
def test():
if e1.get() == "老甲鱼":
print("正确!")
return True
else:
print("错误!")
e1.delete(0, "end")
return False
v = StringVar()
e1 = Entry(master, textvariable=v, validate="focusout", validatecommand=test)
e2 = Entry(master)
e1.pack(padx=10, pady=10)
e2.pack(padx=10, pady=10)
master.mainloop()
然后,invalidcommand 选项指定的函数只有在 validatecommand 的返回值为 False 的时候才被调用。
下边的例子中,在第一个输入框输入“老甲鱼”,并通过 Tab 键将焦点转移到第二个输入框,validatecommand 指定的验证函数被触发并返回 False,接着 invalidcommand 被触发:
from tkinter import *
master = Tk()
def test():
if e1.get() == "老甲鱼":
print("正确!")
return True
else:
print("错误!")
e1.delete(0, "end")
return False
def test2():
print("我被调用了......")
return True
v = StringVar()
e1 = Entry(master, textvariable=v, validate="focusout",\
validatecommand=test, invalidcommand=test2)
e2 = Entry(master)
e1.pack(padx=10, pady=10)
e2.pack(padx=10, pady=10)
master.mainloop()
最后,其实 Tkinter 还有隐藏技能,不过需要冷却才能触发,请听老甲鱼一一道来…
Tkinter 为验证函数提供一些额外的选项:
额外选项 | 含义 |
'%d' | 操作代码:0 表示删除操作;1 表示插入操作;2 表示获得、失去焦点或 textvariable 变量的值被修改 |
'%i' | 1. 当用户尝试插入或删除操作的时候,该选线表示插入或删除的位置(索引号) 2. 如果是由于获得、失去焦点或 textvariable 变量的值被修改而调用验证函数,那么该值是 -1 |
'%P' | 1. 当输入框的值允许改变的时候,该值有效 2. 该值为输入框的最新文本内容 |
'%s' | 该值为调用验证函数前输入框的文本内容 |
'%S' | 1. 当插入或删除操作触发验证函数的时候,该值有效 2. 该选项表示文本被插入和删除的内容 |
'%v' | 该组件当前的 validate 选项的值 |
'%V' | 1. 调用验证函数的原因 2. 该值是 'focusin','focusout','key' 或 'forced'(textvariable 选项指定的变量值被修改)中的一个 |
'%W' | 该组件的名字,不过是 tk 变量在内部注册的名字,为一串数字。 |
为了使用这些选项,你可以这样写:validatecommand=(f, s1, s2, …)
其中,f 就是你“冷却后”的验证函数名,s1、s2、s3 这些就是上面表里额外的选项,这些选项会作为参数依次传给 f 函数。我们刚刚说了,使用隐藏技能前需要冷却,其实就是调用 register() 方法将验证函数包装起来:
(这个f也就是刚刚的上个例子validatecommand=test方法,在这里直接套进去不行,因为这样子Tkinter他不认,认不了你,所以需要先调用register() 方法将验证函数先包装起来,包装成Tkinter能够认出来的东西)
from tkinter import *
master = Tk()
v = StringVar()
def test(content, reason, name):
if content == "老甲鱼":
print("正确!")
print(content, reason, name)
return True
else:
print("错误!")
print(content, reason, name)
return False
testCMD = master.register(test)
e1 = Entry(master, textvariable=v, validate="focusout", validatecommand=(testCMD, '%P', '%v', '%W'))
e2 = Entry(master)
e1.pack(padx=10, pady=10)
e2.pack(padx=10, pady=10)
master.mainloop()
(解析:对比上个例子可以发现,test方法不再是没有参数的方法了,他有三个参数,是在Entry组件的validatecommand选项中出现:validatecommand=(testCMD, ‘%P’, ‘%v’, ‘%W’),第一个%P查看上面的表可以知道是表示说他的值是输入框的最新文本内容,就是当输入框的值有改变的时候,%P就会有内容作为参数传到test方法的content参数,另外两个也是类似的道理,他们三个作为额外选项,作为参数传给test方法,然后%v就是表示该组件当前的 validate 选项的值,%W就是表示该组件的名字,在这里该组件就是e1,输出的就是e1在Tkinter里边注册的名字)
※下面可以开始来写计算器了
(刚才的要求就是输入框不能存在数字以外的东西,有的小伙伴要获得文本框的内容,他可能会用e1.get来获取,然后设置validate = “key”,即表示当输入框有任何改变的时候就会触发调用验证的函数验证输入的内容正不正确,如果设置为key的话,就不能使用e1.get或者说一个textvariable的.get来获取内容了, 因为validate选项被指定为key的时候,有任何输入操作都会立刻被拦截,然后去调用验证函数,然后验证完之后,只有验证函数返回True,他才会将这个内容放到变量里边那个textvariable关联的变量里边,所以这里要用那个加强版的技能,就是上个例子的额外选项。%P来实现,%P就是来实现输入框发生任何改变就会获得输入框里边的内容,然后传递过去,)
from tkinter import *
master = Tk()
frame = Frame(master)
frame.pack(padx =10,pady=10)
v1 = StringVar()
v2 = StringVar()
v3 = StringVar()
def test(content):
if content.isdigit() or content == "":
return True
else:
return False
testCMD = master.register(test) #使用额外选项时需要先将测试函数包装
e1 = Entry(frame, width=10,textvariable=v1, validate="key",\
validatecommand=(testCMD, '%P')).grid(row = 0,column=0)
Label(frame,text="+").grid(row = 0,column=1)
e2 = Entry(frame, width=10,textvariable=v2, validate="focusout",\
validatecommand=(testCMD, '%P')).grid(row = 0,column=2)
Label(frame,text="=").grid(row = 0,column=3)
e3 = Entry(frame,width=10,textvariable=v3,state = "readonly").grid(row = 0,column=4)
def calc():
result = int(v1.get())+int(v2.get())
v3.set(str(result))
Button(frame,text = "计算结果",command =calc).grid(row = 1,column=2,pady=5)
master.mainloop()
(解析:首先这个计算器的布局就是第一行三个输入框,和两个Label组件分别显示"+“号和”="号,前面两个输入框需要验证他输入的合法性,只能是数字,第三个是放结果的,他不要验证,但要设置一个state属性的值为readonly,就是只能读取,不能修改,和disable的区别就是,readonly还可以复制,而disable就是什么操作都会被被禁止
还有一个需要注意的就是如果validate的值是key的话,测试函数test返回的是True,那么你输入的内容就会在输入框里边保留,很智能,如果返回是False,他就会自动帮你清除掉,所以当输入的不是数字时就会返回False,就不会显示出来)
下一篇: 二叉树的非递归遍历模板