本文介绍Listbox控件。
Listbox控件的显示主体就是一个选项列表(items list),每个item一行。当创建一个Listbox控件对象时,该对象没有选项(item)。item可以支持两种方法创建。item可以被删除。一个或多个item可以被选中,然后做相应的事情。还是那个套路,结合实例介绍一下常用的属性和方法。
class Listbox(Widget, XView, YView)
看到这个类的继承关系,就知道可以使用scrollbar。
Listbox(master=None, cnf={}, **kw)
master还是指父窗口对象
设置背景颜色
设置边框宽度
设置前景色(文字颜色)
设置光标显示样式
如果你阅读过本系列文章的checkbutton或radiobutton,你将很容易的理解这个属性的作用。listvariable的值是一个StringVar变量,该变量的值是一个列表或元组,用来作为listbox的item。
selectmode决定了item怎样被选择的问题?是选一个呢还是选多个?要怎么实现这个"选"?
browse - 默认值。只能选一个选项,即使你按住鼠标拖动,也是选择最后鼠标停留的那个选项
extended - 通过按住鼠标拖动,选择多个选项
singe - 也是只能选择一个选项且只支持鼠标单击,鼠标按住并拖动无效,这也是与browse有差异的地方,但是我并没有感觉这个属性有啥用
multiple - 选择多个选项且支持鼠标单击,鼠标按住并拖动无效
我们来看个简单的例子
from tkinter import Tk,Listbox,StringVar
main_win = Tk()
main_win.title('渔道的listbox控件')
width = 300
height = 300
main_win.geometry(f'{width}x{height}')
items = ('apple', 'orange', 'pear', 'grape')
strvar_items = StringVar(value=items)
Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items, selectmode='multiple').pack() # 自行替换selectmode的值来感受不同值的差异
main_win.mainloop()
上面这个例子介绍了怎样给listbox添加items,但是如果想动态的增加item呢?那就需要用到insert()函数。
获取index指定的item的索引号
listbox的常见index
有如下几种:
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross')
l.pack()
for item in range(100):
l.insert("end", item)
print(l.index("active")) # 输出 0
print(l.index("anchor")) # 输出 100
对listbox实现不同方式的item插入
items = ('apple', 'orange', 'pear', 'grape')
strvar_items = StringVar(value=items)
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items)
l.pack()
items2 = ['watermelon', 'banana']
# 顺序头插
# for i, item in enumerate(items2):
# print(l.index("active"))
# print(l.index("anchor"))
# l.insert(i, item)
# 逆序头插
# for item in items2:
# print(l.index("active"))
# print(l.index("anchor"))
# l.insert(0, item)
# 尾插
for item in items2:
print(l.index("active"))
print(l.index("anchor"))
l.insert("end", item)
三种插入方式,自行执行,观察其差异。
item不仅支持插入也支持删除,使用delete()函数来实现
删除first到last的item
items = ('apple', 'orange', 'pear', 'grape')
strvar_items = StringVar(value=items)
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items, selectmode='extended')
l.pack()
l.delete(1,2) # 删除第1个和第2个item
获取first到last的item 列表
items = ('apple', 'orange', 'pear', 'grape')
strvar_items = StringVar(value=items)
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items, selectmode='extended')
l.pack()
print(l.get(1,2)) # 输出 ('orange', 'pear')
获取当前被选中的item(s)的索引号
设置first到last的item(s)被选中。也可使用select_set()。
items = ('apple', 'orange', 'pear', 'grape')
strvar_items = StringVar(value=items)
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items, selectmode='extended')
l.pack()
print(l.curselection()) # 输出为 空元组 ()
l.select_set(1, 3)
print(l.curselection()) # 输出为 (1, 2, 3)
获取listbox中item的个数
获取index指定的item的属性(background, bg, foreground, fg, selectbackground, selectforeground)
items = ('apple', 'orange', 'pear', 'grape')
strvar_items = StringVar(value=items)
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items)
l.pack()
print(l.size()) # 输出 4
print(l.itemconfig(0))
# {'background': ('background', 'background', 'Background', '', ''), 'bg': ('bg', '-background'), 'fg': ('fg', '-foreground'), 'foreground': ('foreground', 'foreground', 'Foreground', '', ''), 'selectbackground': ('selectbackground', 'selectBackground', 'Foreground', '', ''), 'selectforeground': ('selectforeground', 'selectForeground', 'Background', '', '')}
选中的item的文字的颜色
选中的item的背景的颜色
选中的item的边框宽度
items = ('apple', 'orange', 'pear', 'grape')
strvar_items = StringVar(value=items)
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items, selectbackground='red', selectforeground='blue', selectborderwidth=5, activestyle='dotbox')
l.pack()
表示当某个item被选中后,该item的显示样式。
items = ('apple', 'orange', 'pear', 'grape')
strvar_items = StringVar(value=items)
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items, selectbackground='red', selectforeground='blue', selectborderwidth=20, activestyle='dotbox')
# l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items, selectbackground='red', selectforeground='blue', selectborderwidth=20, activestyle='none')
# l = Listbox(main_win, bg='yellow', bd=10, cursor='cross', listvariable=strvar_items, selectbackground='red', selectforeground='blue', selectborderwidth=20, activestyle='underline')
l.pack()
因为类间关系,Listbox可以和scrollbar结合使用。scrollbar和其他控件的组合原理之前已在tkinter-Scrollbar详解一文中做了详细的阐述(Text和Scrollbar)。有了前面的基础,就很容易使用scrollbar和相关控件的关联,这里给出一个示例(Listbox和Scrollbar)
指定与水平滚动条的回调函数
指定与垂直滚动条的回调函数
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross')
l.pack(side=LEFT, fill=BOTH)
scrollbar_v = Scrollbar(main_win)
scrollbar_v.pack(side=LEFT, fill=Y)
for item in range(100):
l.insert("end", item)
scrollbar_v.config(command=l.yview)
l.config(yscrollcommand=scrollbar_v.set)
测试发现,Listbox没有command属性,那么需要使用bind函数来关联事件。本文的重点不是bind机制,会另写一篇文章详细介绍。
def select_cb(*args):
idxs = l.curselection()
print(f'idxs:{idxs}')
l = Listbox(main_win, bg='yellow', bd=10, cursor='cross')
l.pack(side=LEFT, fill=BOTH)
scrollbar_v = Scrollbar(main_win)
scrollbar_v.pack(side=LEFT, fill=Y)
for item in range(100):
l.insert("end", item)
scrollbar_v.config(command=l.yview)
l.config(yscrollcommand=scrollbar_v.set)
l.bind('<>' , select_cb) # 将item的选择事件和select_cb()绑定
通过bind函数绑定 虚拟事件ListboxSelect,每选择一个item,就会触发select_cb调用。