目录
- 列表框Listbox简介
- Listbox 的初步应用
- 建立列表框项目 insert()
- Listbox的基本操作
- 列出列表框的选项数量 size()
- 选取特定索引项 selection_set()
- 删除特定索引项
- 传回指定的索引项 get()
- 传回所选取项目的索引 curselection()
- 检查指定索引项是否被选取 selection_includes()
- Listbox与事件绑定
- 虚拟绑定应用于单选
- 虚拟绑定应用于多选
- 活用加入和删除项目
- Listbox 项目的排序
- 拖拽 Listbox 中的项目
- 滚动条的设计
- 总结
列表框Listbox简介
列表框(Listbox)是一个显示一系列选项的Widget控件,用户可以进行单项或多项的选择
使用格式如下:
Listbox(父对象, options, ...)
参数:
- 第一个参数:父对象,表示这个列表框将建立在哪一个窗口内
- 第二个参数:options,参数如下
selectmode的参数
Listbox 的初步应用
例子:
import tkinter
root = tkinter.Tk()
root.geometry("300x180")
# 建立listbox1
listbox1 = tkinter.Listbox(root)
listbox1.pack(side=tkinter.LEFT, padx=5, pady=5)
# 建立listbox2
listbox2 = tkinter.Listbox(root, height=5, relief='raised')
listbox2.pack(anchor=tkinter.N, side=tkinter.LEFT, padx=5, pady=5)
root.mainloop()
运行结果:

建立列表框项目 insert()
可以使用insert()方法为列表框建立项目,这个方法的使用格式如下
insert(index, elements)
参数:
- 第一个参数:父index,是项目插入的位置,如果是插在最后面可以使用END
- 第二个参数:elements,插入的字符串
例子:
import tkinter root = tkinter.Tk() # 建立listbox1 listbox1 = tkinter.Listbox(root) listbox1.pack(padx=5, pady=5) # 插入的位置与信息 listbox1.insert(tkinter.END, 'abc') listbox1.insert(tkinter.END, '123') listbox1.insert(tkinter.END, '!$#') root.mainloop()
运行结果:

其实也可以这样
listbox1.insert(tkinter.END, 'abc', '123', '!$#')
运行结果也是一样的
如果有很多的项目需要插入,我们可以使用循环的方式来进行
例子:
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
root.mainloop()
运行结果:

例子:
重新设计程序,使列表框可以多选
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.MULTIPLE)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
root.mainloop()
运行结果:

例子:
重新设计,单击一个项目,按住Shift可以选择一个区间内的项目
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
root.mainloop()
运行结果:

前面是单击并拖拽,后面是使用Shift键选择一个区间内的项目
使用insert(ACTIVE, elements),表示是在目前选项前面加入一个项目,如果尚未选择选项则此ACTIVE是0
例子:
使用ACTIVE
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
listbox1.insert(tkinter.ACTIVE, '豆皮', '牛肉面', '汤圆')
root.mainloop()
运行结果:

显示已经在最上面了,也就是一次性在最上面插入了三个项目
Listbox的基本操作
下面是一些常用的Listbox 控件操作的方法
列出列表框的选项数量 size()
例子:
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
print('数量是:', listbox1.size())
root.mainloop()
运行结果:
数量是: 12
选取特定索引项 selection_set()
如果selection_set() 方法内含一个参数,表示选取这个索引项,这个功能常被用于在建立Listbox 后,设定初次选择的项目,通俗易懂的说,就是一进去默认选的是哪一个
例子:
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
# 这里设置默认选定的索引项
listbox1.select_set(1)
root.mainloop()
运行结果:

如果设置两个索引值,就表示选取区间选项,第一个参数是起始索引项,第二个参数是区间的结束索引项
例子:
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
# 这里设置默认选定的索引项
listbox1.select_set(1, 3)
root.mainloop()
运行结果:

删除特定索引项
如果delete() 方法内含一个参数,表示删除这个索引项
例子
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
# 这里设置删除选定的索引项
listbox1.delete(0)
root.mainloop()
运行结果:

可以很自然的看到“热干面”选项已经不见了
如果delete() 有两个参数是,表示选取区间选项,第一个参数是区间的起始索引项,第二个参数是区间的结束索引项
例子:
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
# 这里设置删除选定的索引项
listbox1.delete(0, 1)
root.mainloop()
运行结果:

可以看到“热干面、担担面”两个选项已经删除了
传回指定的索引项 get()
如果get() 方法内含一个参数,表示传回这个索引项的元素内容
例子:
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
print(listbox1.get(1))
root.mainloop()
运行结果:
担担面
如果在get() 方法内有两个参数,则表示传回区间选项,第一个参数是区间的起始索引项,第二个参数是区间的结束索引项,传回的值用元组方式传回
例子:
import tkinter
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
print(listbox1.get(1, 3))
root.mainloop()
运行结果:
('担担面', '炸酱面', '面窝')
传回所选取项目的索引 curselection()
注意!注意!是索引,不是索引项
例子:
import tkinter
def show():
    index = listbox1.curselection()
    print(index)
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
button = tkinter.Button(root, text='print', command=show)
button.pack()
root.mainloop()
运行结果:

我们可以结合get() 方法使用
例子:
def show():
    index = listbox1.curselection()
    for i in index:
        print(listbox1.get(i))
运行结果:

检查指定索引项是否被选取 selection_includes()
如果指定索引项被选取会传回True,否则传回False
例子:
import tkinter
def show():
    # 检查第二个选项有无被选取
    print(listbox1.select_includes(1))
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆', '混沌', '糊汤粉', '饺子', '豆皮', '牛肉面', '汤圆']
# 建立listbox1
listbox1 = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
listbox1.pack(padx=5, pady=5)
# 插入的位置与信息
for food in foods:
    listbox1.insert(tkinter.END, food)
button = tkinter.Button(root, text='print', command=show)
button.pack()
root.mainloop()
运行结果:

Listbox与事件绑定
虚拟绑定应用于单选
当Listbox执行选取操作时会产生<<ListboxSelection>>虚拟事件,可以由此设置事件处理程序
例子:
import tkinter
def show(event):
    # 取得事件对象object
    object = event.widget
    # 取得所选的项目索引
    index = object.curselection()
    # 由索引取得所选的项目,关联到label中
    var.set(object.get(index))
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆']
# 显示区
var = tkinter.StringVar()
label = tkinter.Label(root, textvariable=var)
label.pack(pady=5)
# 列表框
lb = tkinter.Listbox(root)
for i in foods:
    lb.insert(tkinter.END, i)
lb.bind("<<ListboxSelect>>", show)
lb.pack(pady=5)
root.mainloop()
运行结果:

单击Listbox中选项时会产生虚拟的<<ListboxSelection>>事件,此时可以触发itemChanged()方法处理此事件
其实可以省略第四行,直接使用原先的Listbox对象也可以
例子:
def show(event):
    # 取得所选的项目索引
    index = lb.curselection()
    # 由索引取得所选的项目,关联到label中
    var.set(lb.get(index))
运行结果是一样的
或者我们不使用虚拟绑定,直接简单粗鲁的使用单击选项,也行
例子:
lb.bind("<Button-1>", show)
运行结果是一样的!
注意:这种方式pycharm会报错,但是依旧可以运行!
虚拟绑定应用于多选
例子:
import tkinter
def show(event):
    object = event.widget
    indexs = object.curselection()
    for index in indexs:
        print(object.get(index))
    print('------------')
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆']
# 列表框
lb = tkinter.Listbox(root, selectmode=tkinter.EXTENDED)
for i in foods:
    lb.insert(tkinter.END, i)
lb.bind("<<ListboxSelect>>", show)
lb.pack(pady=5)
root.mainloop()
运行结果:

活用加入和删除项目
例子:
import tkinter
def add():
    varAdd = entry.get()
    if (len(varAdd.strip())) == 0:
        return
    listbox.insert(tkinter.END, varAdd)
    entry.delete(0, tkinter.END)
def delete():
    index = listbox.curselection()
    if len(index) == 0:
        return
    listbox.delete(index)
root = tkinter.Tk()
# 输入框
entry = tkinter.Entry(root)
entry.grid(row=0, column=0, padx=5, pady=5)
# 增加按钮
buttonAdd = tkinter.Button(root, text='增加', width=10, command=add)
buttonAdd.grid(row=0, column=1, padx=5, pady=5)
# 列表显示框
listbox = tkinter.Listbox(root)
listbox.grid(row=1, column=0, padx=5, pady=5)
# 删除按钮
buttonDelete = tkinter.Button(root, text='删除', width=10, command=delete)
buttonDelete.grid(row=1, column=1, padx=5, pady=5, sticky=tkinter.N)
root.mainloop()
运行结果:

Listbox 项目的排序
例子:
import tkinter
def show():
    # 获取复选框是否勾选的值,如果勾选,值为True
    if var.get():
        # 定义排序的变量
        rebBool = True
    else:
        rebBool = False
    # 把我们列表框的几个值获取并转换成列表,方便排序
    listTem = list(listbox.get(0, tkinter.END))
    # 排序
    sortedList = sorted(listTem, reverse=rebBool)
    # 删除之前存在的列表框的值
    listbox.delete(0, tkinter.END)
    # 重新插入我们排序好的列表框的值
    for i in sortedList:
        listbox.insert(tkinter.END, i)
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆']
listbox = tkinter.Listbox(root)
for food in foods:
    listbox.insert(tkinter.END, food)
listbox.pack(padx=10, pady=5)
# 创建排序按钮
button = tkinter.Button(root, text='排序', command=show)
button.pack(side=tkinter.LEFT, padx=10, pady=5)
var = tkinter.BooleanVar()
cheakbutton = tkinter.Checkbutton(root, text='从大到小排序', variable=var)
cheakbutton.pack(side=tkinter.LEFT)
root.mainloop()
运行结果:

拖拽 Listbox 中的项目
例子:
import tkinter
# 处理单击选项
def show(event):
    # nearest可以传回最接近y坐标在Listbox的索引
    # 传回目前选项的索引
    listbox.index = listbox.nearest(event.y)
# 处理拖拽选项
def showInfo(event):
    # 获取目前选项的新索引
    newIndex = listbox.nearest(event.y)
    # 判断,如果向上拖拽
    if newIndex < listbox.index:
        # 获取新位置的内容
        x = listbox.get(newIndex)
        # 删除新内容
        listbox.delete(newIndex)
        # 将新内容插入,相当于插入我们移动后的位置
        listbox.insert(newIndex + 1, x)
        # 把需要移动的索引值变成我们所希望的索引,达到了移动的目的
        listbox.index = newIndex
    elif newIndex > listbox.index:
        # 获取新位置的内容
        x = listbox.get(newIndex)
        # 删除新内容
        listbox.delete(newIndex)
        # 将新内容插入,相当于插入我们移动后的位置
        listbox.insert(newIndex - 1, x)
        # 把需要移动的索引值变成我们所希望的索引,达到了移动的目的
        listbox.index = newIndex
root = tkinter.Tk()
foods = ['热干面', '担担面', '炸酱面', '面窝', '油条', '豆浆']
listbox = tkinter.Listbox(root)
for food in foods:
    listbox.insert(tkinter.END, food)
    listbox.bind('<Button-1>', show)
    listbox.bind('<B1-Motion>', showInfo)
listbox.pack(padx=10, pady=5)
root.mainloop()
运行结果:

程序中用到的方法
nearest(event.y)
上述代码行,可以传回最接近y坐标在Listbox中的索引。当有单击操作时会触发getIndex()方法,第4行可以传回目前选项的索引,在拖拽过程中会触发gragJob()方法,在第7行可以传回新选项的索引,因为在拖拽过程中,这个方法会不断的被触发,所以至于被触发多少次视移动速度而定
假如移动担担面,它的索引是1, 咱们向下拖拽,整个流程如下
- 新索引位置为2
- 获得索引内容 ‘面窝’,参照第27行
- 删除新内容 ‘面窝’,参照第29行
- 将 ‘面窝’ 内容插入在索引1的位置,相当于插入到我们移动前的位置,参照第31行
- 这个时候把新的索引位置传给 ‘担担面’ ,根据索引来变换位置,变成了2,这样就达到了移动的目的了,参照第33行
滚动条的设计
在默认环境中Listbox 是没有滚动条的,但是如果选项太多,将造成部分选项无法显示,可以将滚动条Scrollbar控件加入Listbox中
注:Scrollbar控件除了可以应用在Listbox上,也可以应用在Text和Canvas上
使用格式如下:
Scrollbar(父对象, options, ...)
参数:
- 第一个参数:父对象,表示这个滚动条将建立在哪一个窗口内
- 第二个参数:options,参数如下
例子:
import tkinter
root = tkinter.Tk()
sc = tkinter.Scrollbar(root)
sc.pack(side=tkinter.RIGHT, fill=tkinter.Y)
# 列表动,滚动条跟着动
lb = tkinter.Listbox(root, yscrollcommand=sc.set)
for i in range(50):
    lb.insert(tkinter.END, "列表 " + str(i))
lb.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=True)
# 滚动条动,列表跟着动
sc.config(command=lb.yview)
root.mainloop()
运行结果:

总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。
