zoukankan      html  css  js  c++  java
  • GUI的最终选择 Tkinter(四):Entry、Listbox、Scrollbar和Scale组件

    Entry组件

    Entry组件就是平时所说的输入框。输入框是程序员用到的最多的一个程序,例如在输入账号和密码的时候需要提供两个输入框,用于接收密码的输入框还会有星号将实际输入的内容隐藏起来。

    Tkinter组件之间的许多方法和选项之间都是通用的,例如在输入框中用代码添加删除内容,同样也是使用insert()和delete()方法

    1 from tkinter import *
    2 
    3 root = Tk()
    4 e = Entry(root)
    5 e.pack(padx=20,pady=20)
    6 e.delete(0,END)
    7 e.insert(0,"默认文本。。。")
    8 mainloop()

    如图所示:

    获取输入框里面的内容,可以使用Entry组件的get()方法。当然也可以将一个Thinter的变量(通常是StringVar)挂钩到textvariablex选项,然后通过变量的get()方法获取。

    继续看下面的例子,添加一个按钮,当单击按钮时候,获取输入框的内容并打印出来,然后清空输入框。单击“获取信息”按钮,在IDIE中输入框中的内容显示出来。

     1 from tkinter import *
     2 
     3 root = Tk()
     4 #Tkinter总共提供了三种布局方法:pack(),grid()和place()
     5 #grid()方法允许你用表格的形式爱管理组件的位置
     6 #row选项代表行,column选项代表列
     7 #例如:row=1,column=2表示第二行第三列(0表示第一行)
     8 Label(root,text="作品:").grid(row=0)
     9 Label(root,text="作者:").grid(row=1)
    10 e1 = Entry(root)
    11 e2 = Entry(root)
    12 e1.grid(row=0,column=1,padx=10,pady=5)
    13 e2.grid(row=1,column=1,padx=10,pady=5)
    14 def show():
    15     print("作品:《%s》"%e1.get())
    16     print("作者:%s"%e2.get())
    17     e1.delete(0,END)
    18     e2.delete(0,END)
    19 #如果表格大于组件,那么可以使用sticky选项来设置组件的位置
    20 #同样需要使用N,E,S,W以及他们的组合NE,SE,SW,NW来表示方位
    21 Button(root,text="获取信息",width=10,command=show).grid(row=3,column=0,sticky=W,padx=10,pady=5)
    22 Button(root,text="退出",width=10,command=root.quit).grid(row=3,column=1,sticky=E,padx=10,pady=5)
    23 mainloop()

    执行结果:

     如果你手残的话,肯定会发现单击 “退出”按钮没有反应,这是因为python的IDIE也是使用Tkinter设计的,因此当程序使用IDIE运行的时候,就会出现此类冲突,解决方法:在cmd中运行脚本

    如果想设计一个密码输入框,即使用星号(*)代替用户输入的内容,只需要设计show选项即可。

     1 from tkinter import *
     2 
     3 root = Tk()
     4 Label(root,text="账号:").grid(row=0)
     5 Label(root,text="密码:").grid(row=1)
     6 v1 = StringVar()
     7 v2 = StringVar()
     8 e1 = Entry(root,textvariable=v1)
     9 e2 = Entry(root,textvariable=v2,show="*")
    10 e1.grid(row=0,column=1,padx=10,pady=5)
    11 e2.grid(row=1,column=1,padx=10,pady=5)
    12 def show():
    13     print("账号:%s"%v1.get())
    14     print("作者:%s"%v2.get())
    15     e1.delete(0,END)
    16     e2.delete(0,END)
    17 Button(root,text="芝麻开门",width=10,command=show).grid(row=3,column=0,sticky=W,padx=10,pady=5)
    18 Button(root,text="退出",width=10,command=root.quit).grid(row=3,column=1,sticky=E,padx=10,pady=5)
    19 mainloop()

    执行结果:

     

     另外,Entry组件还支持验证输入内容的合法性,例如输入框要求输入的是数字,用户输入了字母就输入“非法”操作了,实现该功能需要通过设置validate,validatecommand和invalidcommand三个选项。

    首先是启用验证的“开关”是validate选项,该选项可以设置的值如下表所示:

    含义
    focus 当Entry组件获取或失去焦点的时候验证
    focusin 当Entry组件获得焦点的时候验证
    focusout 当Entry组件失去焦点的时候验证
    key 当输入框被编辑的时候验证
    all 当出现上面任何一种情况的时候验证
    none 当关闭验证功能。默认设置该选项(即不启动验证)。注意,是字符串的‘none’,而非None

    其次是validatecommand选项指定一个验证函数,该函数只能返回True或False表示验证的结果。一般情况下验证函数只需要知道输入框的内容即可。可以通过Entry组件的get()方法获得该字符串。

    下面的例子中,在第一个输入框中输入“python3”并通过Tab键将焦点转移到第二个输入框的时候,验证功能被成功触发:

     1 from tkinter import *
     2 root = Tk()
     3 def test():
     4     if e1.get() =="python3":
     5         print("正确")
     6         return True
     7     else:
     8         print("错误")
     9         e1.delete(0,END)
    10         return False
    11 v1 = StringVar()
    12 e1 = Entry(root,textvariable=v1,validate="focusout",validatecommand=test)
    13 e2 = Entry(root)
    14 e1.pack(padx=10,pady=10)
    15 e2.pack(padx=10,pady=10)
    16 mainloop()

    执行结果:

    最后,invalidcommand选项指定的函数只有在validatecommand的返回值为False的时候才会被调用。

    在下面的例子中,在第一个输入框中输入的“python3”,并通过Tab键将焦点转移到第二个输入框,validatecommand指定的验证函数被触发并返回False,接着invalidatecommand被触发。

     1 from tkinter import *
     2 root = Tk()
     3 def test():
     4     if e1.get() =="python3":
     5         print("正确")
     6         return True
     7     else:
     8         print("错误")
     9         e1.delete(0,END)
    10         return False
    11 def test2():
    12     print("我被调用了。。。")
    13     return True
    14 v1 = StringVar()
    15 # e1 = Entry(root,textvariable=v1,validate="focusout",validatecommand=test)
    16 e1 = Entry(root,textvariable=v1,validate="focusout",validatecommand=test,invalidcommand=test2)
    17 e2 = Entry(root)
    18 e1.pack(padx=10,pady=10)
    19 e2.pack(padx=10,pady=10)
    20 mainloop()

    执行结果:

    其实,Tkinter还有个一“隐藏技能”,Tkinter为了验证函数提供 了一些额外的选项,如下表

    选项 含义
    %d 操作代码,0表示删除操作,1表示插入操作,2表示获得、失去焦点或textvariable变量的值被修改
    %r 当用户尝试插入或删除操作的时候,该选项表示插入或删除的位置(索引号)如果是由于获得、失去焦点或textvariable变的值被修改而调用验证函数,那么该值是-1
    %p 当输入框的值允许改变的时候,该值有效,该值为输入框的最新文本内容
    %s 该值为调用验证函数前输入框的文本内容
    %S 当插入或删除操作触发验证函数的时候,该值有效选项表示文本被插入和删除的内容
    %v 该组件当前的validate选项的值
    %V 调用验证函数的原因该值是focusin,focusout,key或forced(textvariable选项指定的变量值被修改)中一个
    %W 该组件的名字

    为了使用这些选项,你也可以这样写:

    validatecommand = (f,s1,s2,...)

    其中,f是验证函数名,s1,s2等是额外的选项,这些选项会作为参数一次性传递给f函数。在此之前,需要调用register()方法将验证函数包装起来。

     1 from tkinter import *
     2 root = Tk()
     3 v = StringVar()
     4 def test(content,reason,name):
     5     if content =="python3":
     6         print(content,reason,name)
     7         return True
     8     else:
     9         print("错误")
    10         print(content,reason,name)
    11         return False
    12 testCDM = root.register(test)
    13 e1 = Entry(root,textvariable=v,validate="focusout",validatecommand=(testCDM,'%P','%v','%W'))
    14 e2 = Entry(root)
    15 e1.pack(padx=10,pady=10)
    16 e2.pack(padx=10,pady=10)
    17 mainloop()

    执行结果:

    下面我们来写一个简单的计算器

     1 from tkinter import *
     2 
     3 root = Tk()
     4 frame = Frame(root)
     5 frame.pack(padx=10,pady=10)
     6 v1 = StringVar()
     7 v2 = StringVar()
     8 v3 = StringVar()
     9 def test(content):
    10     #注意,这里不能使用e1.get()或者来获取输入的内容
    11     #因为validate选项指定"key"的时候,有任何输入操作都会被拦截到这个函数中
    12     #也就是说先拦截,只有这个函数返回True,那么输入的内容才会到变量里面
    13     #所以要使用%P来获取最新的输入框内容
    14     if content.isdigit():
    15         return True
    16     else:
    17         return False
    18 testCDM = root.register(test)
    19 Entry(frame,textvariable=v1,width=10,validate='key',validatecommand=(testCDM,'%P')).grid(row=0,column=0)
    20 Label(frame,text='+').grid(row=0,column=1)
    21 Entry(frame,textvariable=v2,width=10,validate='key',validatecommand=(testCDM,'%P')).grid(row=0,column=2)
    22 Label(frame,text='=').grid(row=0,column=3)
    23 Entry(frame,textvariable=v3,width=10,validate='key',validatecommand=(testCDM,'%P')).grid(row=0,column=4)
    24 def calc():
    25     result =  int(v1.get()) + int(v2.get())
    26     v3.set(result)
    27 Button(frame,text="计算器",command=calc).grid(row=1,column=2,pady=5)
    28 mainloop()

    执行结果:

     Listbox组件

    如果需要提供选择给用户选择,单选可以用Radiobutton组件,多选可以用Checkbutton组件。但是如果提供的选项非常多,例如选择你所在的城市,通过Radiobutton和Checkbutton组件来实现直接导致的结果就是,用户界面存放不了那么多按钮。

    这个时候就需要考虑使用Listbox组件了,Listbox组件是以列表形式显示出来,并支持滚动操作,所以对于需要大量选项的情况下会更好用点。

    当创建一个Listbox组件的时候,它是空的(里面什么都没有),所以,首先要做的第一个事情就是添加一行或多行文本进去。使用insert()方法添加两个参数:第一个参数是插入的索引号,第二个参数是插入的字符串。索引号通常是项目的序号(第一项的序号是0),当然对于多个项目,应该使用循环。

     1 from tkinter import *
     2 master = Tk()
     3 theLB = Listbox(master,setgrid=True) #创建一个空列表
     4 theLB.pack()
     5 #向列表中添加数据
     6 for item in ["恐龙蛋","鹅蛋","鸭蛋","鸡蛋"]:
     7     theLB.insert(END,item)
     8 theButton = Button(master,text="删除",command=lambda x=theLB:x.delete(ACTIVE))
     9 theButton.pack()
    10 mainloop()

    执行结果:

    使用delete()方法删除列表中的项目,最常用的操作是删除列表中的所有项目:listbox.delete(0,END)

    #跟END一样,这个AXTIVE是一个特殊的索引号,表示当前被选中项目
    theButton = Button(master,text="删除",command=lambda x=theLB:x.delete(ACTIVE)) theButton.pack()

     最后,这个Listbox组件根据selectmode选项提供了四种不同的选择模式:SINGLE(单选),BROWSE(也是单选,但拖动鼠标或通过方向键可以直接改变选项),MELTIPLE(多选)和EXTENDED(也是多选,但是需要同时按照Shift键或Ctrl键拖动光标实现)。默认的选中模式是BROWSE.

    选项增多接踵而来的麻烦也会增多,例如使用Listbox组件默认只能显示10个项目,而有11个怎么办了

    1 from tkinter import *
    2 master = Tk()
    3 theLB = Listbox(master,setgrid=True) #创建一个空列表
    4 theLB.pack()
    5 #往列表中增加数据
    6 for item in range(20):
    7     theLB.insert(END,item)
    8 mainloop()

    执行结果:

    共有20个数字,但是只显示了10个,只能利用上下键或者鼠标滚动才能显示下面数字,如果想让下面的数字都显示,第一个方法就是修改height选项

    theLB = Listbox(master,setgrid=True,height=14)

    执行结果:

    可以看到height选项虽然能达到目的,但是少了就不显示,多了就超出屏幕,所以我们可以用第二种方法就是在右边添加一个滚动条。

    Scrollbar组件

    滚动条是一个独立的组件,但是他平时都是和其他组件配合使用,下面一个例子看下如何使用垂直滚动条。

    为了在某个组件上安装垂直滚动条,需要做两件事

    1、设置组件的yscrollbarcommand选项Scrollbar组件的set()方法

    2、设置Scrollbar组件的command选项为该组件的yview()方法

     1 if __name__ == "__main__":
     2     from tkinter import *
     3     master = Tk()
     4     sb = Scrollbar(master)
     5     sb.pack(side=RIGHT,fill=Y)
     6     lb = Listbox(master,yscrollcommand=sb.set)
     7     for i in range(100):
     8         lb.insert(END,str(i))
     9     lb.pack()
    10     sb.config(command=lb.yview)
    11     mainloop()

    执行结果:

    这是一个互联互通的过程,当用户操作滚动条进行滚动时,滚动条相应滚动并通过Listbox组件的yview()方法滚动列表框里的内容,同样,当列表框中可视范围发送改变的时候,Listbox也会相应的改变。

    Scale组件

    Scale组件和Scrolbar滚动条组件很相似,都可以滚动,都是条形,但是他们的使用范围是不相同的。Scale组件主要是通过修改选项设置范围以及分辨率(精度)。

    当希望用户输入某个范围的数值,使用Scale组件可以很好地替代Entry组件,创建一个指定范围的Scale组件其实非常容易,只要指定from和to两个关键字即可,但是from本身是python的关键字,为了区分我们在后面加下划线from_

    1 if __name__ == "__main__":
    2     from tkinter import *
    3     root = Tk()
    4     Scale(root,from_=0,to=20).pack()
    5     Scale(root,from_=0,to=200,orient=HORIZONTAL).pack()
    6     mainloop()

    执行结果:

    可以使用get()方法获取当前滑动的位置:

     1 if __name__ == "__main__":
     2     from tkinter import *
     3     root = Tk()
     4     s1 = Scale(root, from_=0, to=20)
     5     s1.pack()
     6     s2 = Scale(root, from_=0, to=200, orient=HORIZONTAL)
     7     s2.pack()
     8 
     9     def show():
    10         print(s1.get(),s2.get())
    11     Button(root,text="获取位置",command=show).pack()
    12 
    13     mainloop()

    执行结果:

    可以通过resolution选项控制分辨率(步长),通过tickinterval选项设置刻度:

    1 from tkinter import *
    2 root = Tk()
    3 Scale(root,from_=0,to=20,tickinterval=5,resolution=5,length=200).pack()
    4 Scale(root,from_=0,to=200,tickinterval=10,orient=HORIZONTAL,resolution=10,length=600).pack()
    5 mainloop()

    执行结果:

     

  • 相关阅读:
    用django搭建自己的博客
    python模块调用
    python常用函数
    ubuntu不能访问windows中的文件
    更改ubuntu下mysql的密码
    重拾代码,加油
    java 接收 char字符型
    Git基础
    flask中'bool' object has no attribute '__call__'问题
    基于python的flask的应用实例注意事项
  • 原文地址:https://www.cnblogs.com/pinpin/p/9949339.html
Copyright © 2011-2022 走看看