这节课的主要内容为 Listbox 组件、Scrollbar 组件 和 Scale 组件
在之前的学习中,我们已经知道了,如果说提供选项给客户选择,那么有两种情况,单选的话,我们用 Radiobutton,多选的话,用Checkbutton,如果说提供的选项非常多,比如说选择你所在的城市,那么全国有好几百个城市,使用 Radiobutton 和 Checkbutton 这些组件直接导致的结果就是用户的界面根本就不够存放那么多按钮,这时候你就可以考虑使用我们今天要介绍的 Listbox 组件。
一、Listbox 组件
Listbox 是用列表框的形式给显示出来的,并且支持滚动条操作,所以对于诸如提供大量的选项这样的情况会更适用一些。
我们先来举个简单的例子:
-
import tkinter as tk
-
master = tk.Tk()
-
theLB = tk.Listbox (master)
-
theLB.pack()
-
master.mainloop()
运行一下:
如你所见,刚开始创建出来的时候,是空的,里面什么都没有,没有任何选项,所以我们要做的第一件事就是给它添加选项,添加选项同样是用 insert() 方法, insert() 方法 有两个参数,第一个参数就是添加的位置,第二个参数就是添加的内容。
-
import tkinter as tk
-
master = tk.Tk()
-
theLB = tk.Listbox (master)
-
theLB.pack()
-
theLB.insert(0, "Python")
-
master.mainloop()
这就有一个选项了,我们接着添加,你这里可以使用 "end", "end" 表示最后一个位置。
-
theLB.insert(0, "Python")
-
theLB.insert("end", "来自江南的你")
当然啦,对于特别多的选项,我们肯定不建议这样做,我们用循环。
-
import tkinter as tk
-
master = tk.Tk()
-
theLB = tk.Listbox (master)
-
theLB.pack()
-
for item in ["鸡蛋", "鸭蛋", "鹅蛋", "李狗蛋", "蛋蛋"]:
-
theLB.insert("end", item)
-
master.mainloop()
有插入就肯定有删除,删除的话,我们还是使用 delete() 方法,它有两个参数,第一个是 起始位置,第二个是 结束位置。如果只给定一个参数的话,就是指定这个参数对应的项目。
-
for item in ["鸡蛋", "鸭蛋", "鹅蛋", "李狗蛋", "蛋蛋"]:
-
theLB.insert("end", item)
-
theLB.delete(1)
我们经常要做的就是选中哪一个,就删除哪一个。我们现在做一个例子,我们添加一个独立的按钮,作用就是删除用户选中的项目。
-
import tkinter as tk
-
master = tk.Tk()
-
theLB = tk.Listbox (master)
-
theLB.pack()
-
for item in ["鸡蛋", "鸭蛋", "鹅蛋", "李狗蛋", "蛋蛋"]:
-
theLB.insert("end", item)
-
theButton = tk.Button(master, text = "删除",\
-
command = lambda x = theLB : x.delete("active")) #"active"就是选中的选项
-
theButton.pack()
-
master.mainloop()
运行:
最后我们要说的就是Listbox 组件根据 selectmode 选项提供了四种不同的选择模式:"single"(单选)、"browse"(也是单选,但拖动鼠标或通过方向键可以直接改变选项)、"multiple"(多选)和 "extended"(也是多选,但需要同时按住 Shift 键或 Ctrl 键或拖拽鼠标实现)。默认是 "browse"。
-
theLB = tk.Listbox (master, selectmode = "extended")
-
theLB.pack()
大家可以每一个都试一下,感受一下效果。
选项一多啊,麻烦事就接踵而来,比如说,你发现 Listbox 默认只能显示 10个项目,但是你手头有 11 个项目,那怎么办?
我们来试一下:
-
import tkinter as tk
-
master = tk.Tk()
-
theLB = tk.Listbox (master, selectmode = "extended")
-
theLB.pack()
-
for item in range(11):
-
theLB.insert("end", item)
-
master.mainloop()
只能通过鼠标滚轮才能迫使最后一个项目现身,这样子做往往很容易被用户所忽略。你又没有说下面有东西,谁知道呢?
这样的情况,有两种方法来解决这种尴尬。
第一个方法就是修改 height 选项。
height 选项 用法
1. 设置 Listbox 显示的行数(不是像素)
2. 默认值是 10
我们可以改一下:
theLB = tk.Listbox (master, selectmode = "extended", height = 11)
这样子就没问题了。
修改 height 选项的方法虽然可以达到我们的目的,但是如果项目太多,比如说我们要显示 1000 个,这个方法显然就不适用了。
还有一个更加灵活的方法 就是为 Listbox 添加滚动条。
二、Scrollbar 组件
我们接着就来谈谈 滚动条 组件。滚动条 虽然是一个独立的组件存在,但它几乎都是与其他组件配合使用。下面的例子我们演示如何使用垂直滚动条。
为了在某个组件上安装滚动条,你必须要做两件事:
1、设置该组件的 xscrollbarcommand 或者 yscrollbarcommand 选项为 Scrollbar 组件 的 set() 方法。
2、设置 Scrollbar 组件 的 command 选项 为该组件的 xview() 或者 yview() 方法。
说起来比较复杂,但做起来很简单,我们先来搞个滚动条出来:
-
import tkinter as tk
-
root = tk.Tk()
-
sb = tk.Scrollbar(root)
-
sb.pack()
-
root.mainloop()
运行一下:
我们要把它填充到右边的位置:
sb.pack(side = "right", fill = "y")
然后我们就来增加一个 Listbox:
-
import tkinter as tk
-
root = tk.Tk()
-
sb = tk.Scrollbar(root)
-
sb.pack(side = "right", fill = "y")
-
lb = tk.Listbox(root, yscrollcommand = sb.set)
-
for i in range(200):
-
lb.insert("end", i)
-
lb.pack(side = "left", fill = "both")
-
sb.config(command = lb.yview)
-
root.mainloop()
运行一下:
工作原理:这事实上就是一个互联互通的过程,当用户操作滚动条进行滚动的时候,滚动条首先响应用户的滚动操作,接下来,通过 yview() 方法(Listbox 的内置方法),内容就会自动刷新,然后,如果是 Listbox 藜里面滚动,它就会调用 sb.set() 方法,同时修改滚动条的位置。
三、Scale 组件
既然说到滚动条,我们就来顺带说一下跟滚动条长得很相似的一个组件,叫做 Scale 组件。
我们先来看一下它是什么样的:
-
import tkinter as tk
-
root = tk.Tk()
-
tk.Scale(root).pack()
-
root.mainloop()
虽然它和滚动条长得像,同样都可以滚,都有滑块,都是条形的,但是它们的应用范围可是不一样的。Scale 组件主要是通过滑块来表示某个范围内的一个数字,你可以通过修改 选项 、设置范围以及分辨率(分辨率就是指的步长)。
我们来举个例子:
当你希望用户输入某个范围内的一个数字的时候,你可能会使用Entry 组件,但是Entry 组件不能限制一个范围,你只能给出提示,然后对得到的数字进行检测,这样不方便。你可以直接弄一个 Scale 组件,提供一个范围,然后用户就只能在这个范围内选择。
-
import tkinter as tk
-
root = tk.Tk()
-
tk.Scale(root, from_= 0, to = 52).pack()
-
tk.Scale(root, from_= 0, to = 200, orient = 'horizontal').pack() #orient = 'horizontal' 设置为水平,默认"vertical"是垂直
-
root.mainloop()
获取滑块当前的位置,我们使用的是 get()方法,我们增加一个按钮,来试验一下:
-
import tkinter as tk
-
root = tk.Tk()
-
s1 = tk.Scale(root, from_= 0, to = 52)
-
s1.pack()
-
s2 = tk.Scale(root, from_= 0, to = 200, orient = 'horizontal')
-
s2.pack()
-
def show():
-
print(s1.get(), s2.get())
-
tk.Button(root, text = "获取位置", command = show).pack()
-
root.mainloop()
接下来,你还可以通过 resolution 选项 来控制它的步长,也就是精度;使用 tickinterval 选项 显示刻度。
-
import tkinter as tk
-
root = tk.Tk()
-
tk.Scale(root, from_= 0, to = 52, tickinterval = 5, resolution = 5, length = 200).pack()
-
tk.Scale(root, from_= 0, to = 200, tickinterval = 10, orient = 'horizontal', length = 600).pack()
-
root.mainloop()
为了让所有的刻度都能够排列下去,我们通过 length 选项 设置 Scale 组件的长度 为 200 和 600 像素。