Treeview的基本概念
Treeview是tkinter.ttk的控件,这个控件主要是提供多栏的显示功能,我们可以称其为
树状表格数据(Treeview)。在设计时也可以在左边栏设计成树状结构或是称层次结构,用户
可以显示或隐藏任何部分,这个最左边的栏称为图标栏。
设计Treeview控件的基本思想是,使用Treeview构造方法建立Treeview对象。
它的语法如下。
Treeview(父对象,options,···)
Treeview()方法的第一个参数是父对象,表示这个Treeview将建立在哪一个父对象内。
下列是Treeview()方法内其他常用的options参数。
(1)columns:栏位的字符串,其中,第一个栏位是图标栏默认的,不在此设置范围内,
如果设置columns=("Name","Age"),则控件有三栏,首先是最左栏的图标栏,可以进行展开
(expand)或是隐藏(collapse)操作,另外两栏是Name和Age。
(2)cursor:可以设置光标在此控件上的外观。
(3)displaycolumns:可以设置栏位显示顺序。
1.如果参数是"#all"表示显示所有栏,同时依建立顺序显示。
2.如果设置columns=("Name","Age","Date"),使用insert()插入元素时需要依次插入元素。
同样状况如果使用columns(2,0),(2,0)是指实体索引,则图标栏在最前面,紧跟着是Date栏,
然后是Name栏。这种状况也可以写成columns("Date","Name")
(4)height:控件每行的高度。
(5)padding:可以使用1~4个参数设置内容与控件框的间距。
(6)selectmode:用户可以使用鼠标选择项目的方式。
1.selectmode=BROWSE,一次选择一项,这是默认。
2.selectmode=EXTENDED,一次可以选择多项。
3.selectmode=NONE,无法用鼠标执行选择。
(7)show:默认是设置显示图标栏的标签show="tree",如果省略则是显示图标栏,如果设为
show="headings",则不显示图标栏。
(8)takefocus:默认是True,如果不想被访问可以设为False。
实例:简单建立Treeview控件的应用。
from tkinter import *
from tkinter.ttk import *
root=Tk()
root.title("ch18_1")
menubar=Menu(root)
tree=Treeview(root,columns=("cities"))
tree.heading("#0",text="State")
tree.heading("#1",text="City")
tree.insert("",index=END,text="伊利诺",value="芝加哥")
tree.insert("",index=END,text="加州",value="洛杉矶")
tree.insert("",index=END,text="江苏",value="南京")
tree.pack()
root.mainloop()
运行结果:
简单应用
讲解:tree=Treeview(root,columns=("cities"))建立Treeview控件,此控件
有一个栏位,域名是cities。
tree.heading("#0",text="State")和tree.heading("#1",text="City")使用heading()方法,
在这个方法内建立了栏标题,其中,第一个参数"#0"是指最左栏图标栏位,"#1"是指第一个
栏位,所以这两行分别建立了两个栏标题。
tree.insert("",index=END,text="伊利诺",value="芝加哥")使用inert()方法插入Treeview控件
内容,在这个方法中的第一个参数"",代表父id,因为图标栏未来可以有树状结构,所以有这
一个栏位设计。当所建的栏是是最顶层时,可以用""空字符串处理。第二个参数index=END代表
将资料插入Treeview末端,它的思想与Text控件的END相同。第三个参数text是设置图标栏的
内容。第4个参数的values是设置City的内容。
样例2:在建立Treeview控件时,增加show="heading"参数,将不显示图标栏。
from tkinter import *
from tkinter.ttk import *
root=Tk()
root.title("ch18_1")
menubar=Menu(root)
tree=Treeview(root,columns=("cities"),show="headings")
tree.heading("#0",text="State")
tree.heading("#1",text="City")
tree.insert("",index=END,text="伊利诺",value="芝加哥")
tree.insert("",index=END,text="加州",value="洛杉矶")
tree.insert("",index=END,text="江苏",value="南京")
tree.pack()
root.mainloop()
运行结果:
样例2
insert()方法第4个参数values是设置所插入的内容。如果有多栏时,须使用
values=(value1,value2,···),如果所设置的内容数太少时其他栏僵尸空白,如果所设置
的内容数太多时多出来的内容将被抛弃。
样例3:增加population人口数栏位,其中,人口数的单位是万人。
from tkinter import *
from tkinter.ttk import *
root=Tk()
root.title("ch18_1")
menubar=Menu(root)
tree=Treeview(root,columns=("cities","populations"))
tree.heading("#0",text="State")
tree.heading("#1",text="City")
tree.heading("#2",text="Populations")
tree.insert("",index=END,text="伊利诺",value=("芝加哥","800"))
tree.insert("",index=END,text="加州",value=("洛杉矶","1000"))
tree.insert("",index=END,text="江苏",value=("南京","900"))
tree.pack()
root.mainloop()
运行结果:
样例3
也可以将Python的列表应用于建立栏位内容。
格式化Treeview栏位内容
Treeview控件的column()方法主要用于格式化特定栏位的内容,它的语法格式如下。
column(id,options)
其中,id是指出特定栏位,可以用字符串表达,或是用"#index"索引方式。下列是options
的可能参数。
(1)anchor:可以设置栏内容参考位置。
(2)minwidth:最小栏宽,默认是20像素。
(3)stretch:默认是1,当控件大小改变时栏宽将随着改变。
(4)width:默认栏宽是200像素。
如果使用此方法不含参数,如下所示:
ret=column(id)
将以字典方式传回特定栏所有参数的内容。
样例:格式化,将第1、2栏宽度改为150,同时居中对齐,图标栏则不改变。
from tkinter import *
from tkinter.ttk import *
root=Tk()
root.title("ch18_4")
menubar=Menu(root)
tree=Treeview(root,columns=("cities","populations"))
tree.heading("#0",text="State")
tree.heading("#1",text="City")
tree.heading("#2",text="Populations")
tree.column("#1",anchor=CENTER,width=150)
tree.column("#2",anchor=CENTER,width=150)
tree.insert("",index=END,text="伊利诺",value=("芝加哥","800"))
tree.insert("",index=END,text="加州",value=("洛杉矶","1000"))
tree.insert("",index=END,text="江苏",value=("南京","900"))
tree.pack()
root.mainloop()
建立不同颜色的行内容
建立Treeview控件内容时,常常会需要在不同行之间用不同底色作区分,以方便使用者查看,
若是想设计这方面的程序,可以使用Tet控件的标签。Treeview控件有tag_configure()方法,
可以使用这个方法建立标签,然后定义此标签的格式,可参考下列指令。
tag_configure("tagName",options,···)
上述第一个参数tagName是标签名称,可以用此名称将此标签导入栏位数据。
options的可能参数如下。
(1)background:标签背景颜色。
(2)font:字形设置。
(3)foreground:标签前景颜色。
(4)image:图像与列表同时显示。
要将标签导入栏位使用的是insert()方法,这时需在此方法内增加tags参数设置,如下所示。
insert(···,tags="tagName")
样例:将偶数行使用蓝色底显示。
from tkinter import *
from tkinter.ttk import *
root=Tk()
root.title("ch18_6")
stateCity={"伊利诺":"芝加哥","加州":"洛杉矶",
"德州":"休斯顿","华盛顿州":"西雅图",
"江苏":"南京","山东":"青岛",
"广东":"广州","福建":"厦门"}
tree=Treeview(root,columns=("cities"))
tree.heading("#0",text="State")
tree.heading("cities",text="City")
tree.column("cities",anchor=CENTER)
tree.tag_configure("evenColor",background="lightblue")
rowCount=1
for state in stateCity.keys():
if (rowCount % 2 ==1):
tree.insert("",index=END,text=state,values=stateCity[state])
else:
tree.insert("",index=END,text=state,values=stateCity[state],
tags=("evenColor"))
rowCount+=1
tree.pack()
root.mainloop()
建立层级式的Treeview
层级式(Hierarchy),只要在图标栏先建立top-level的项目id,然后将相关子项目放在所属的
top-level项目d即可。
样例:建立层级式的Treeview控件内容。
from tkinter import *
from tkinter.ttk import *
root=Tk()
root.title("ch18_6")
asia={"中国":"北京","日本":"东京","泰国":"曼谷","韩国":"首尔"}
euro={"英国":"伦敦","法国":"巴黎","德国":"柏林","挪威":"奥斯陆"}
tree=Treeview(root,columns=("capital"))
tree.heading("#0",text="国家")
tree.heading("capital",text="首都")
idAsia=tree.insert("",index=END,text="Asia")
idEuro=tree.insert("",index=END,text="Europe")
for country in asia.keys():
tree.insert(idAsia,index=END,text=country,values=asia[country])
for country in euro.keys():
tree.insert(idEuro,index=END,text=country,values=euro[country])
tree.pack()
root.mainloop()
插入图像
在insert()方法内若是增加image参数可以添加图像,在添加图像时需要考虑的是可能row的
高度不足,所以必须增加高度。这时可以用下列Style()方法处理。
Style().conigure("TreeView","rowheight=xx") #xx是高度设置
样例:设计一个含有图像的Treeview。
from tkinter import *
from tkinter.ttk import *
from PIL import Image,ImageTk
root=Tk()
root.title("ch18_8")
Style().configure("Treeview",rowheight=35)
info=["凤凰新闻App可以获得中国各地最新消息",
"瑞士国家铁路App提供全瑞士火车时刻表",
"可口可乐App是一个娱乐的软件"]
tree=Treeview(root,columns=("说明"))
tree.heading("#0",text="App")
tree.heading("#1",text="功能说明")
tree.column("#1",width=300)
img1=Image.open("news.jpg")
imgObj1=ImageTk.PhotoImage(img1)
tree.insert("",index=END,text="凤凰新闻",image=image=imagObj1,values=insert[0])
img2=Image.open("sbb.jpg")
imgObj2=ImageTk.PhotoImage(img2)
tree.insert("",index=END,text="瑞士铁路",image=imageObj2,values=info[1])
img3=Image.open("coca.jpg")
imgObj3=ImageTk.PhotoImage(img3)
tree.insert("",index=END,text="可口可乐",image=imgObj3,values=info[2])
tree.pack()
root.mainloop()
Selection选项发生与事件触发
Treeview控件中可以有三种选择模式,分别是BROWSE(默认)、EXTENDED、NONE,这是
使用selectmode参数设置的,当有新选择项目发生时会产生虚拟事件<<TreeviewSelect>>,
其实我们可以针对此特性设计相关功能。
样例:
from tkinter import *
from tkinter.ttk import *
def treeSelect(event):
widgetObj=event.widget
itemselected=widgetObj.selection()[0]
col1=widgetObj.item(itemselected,"text")
col2=widgetObj.item(itemselected,"values")[0]
str="{0}:{1}".format(col1,col2)
var.set(str)
root=Tk()
root.title("ch18_9")
stateCity={"伊利诺":"芝加哥","加州":"洛杉矶",
"德州":"休斯顿","华盛顿州":"西雅图",
"江苏":"南京","山东":"青岛",
"广东":"广州","福建":"厦门"}
tree=Treeview(root,columns=("cities"),selectmode=BROWSE)
tree.heading("#0",text="State")
tree.heading("cities",text="City")
tree.column("cities",anchor=CENTER)
tree.tag_configure("evenColor",background="lightblue")
rowCount=1
for state in stateCity.keys():
if (rowCount % 2 ==1):
tree.insert("",index=END,text=state,values=stateCity[state])
else:
tree.insert("",index=END,text=state,values=stateCity[state],
tags=("evenColor"))
rowCount+=1
tree.bind("<<TreeviewSelect>>",treeSelect)
tree.pack()
var=StringVar()
label=Label(root,textvariable=var,relief="groove")
label.pack(fill=BOTH,expand=True)
root.mainloop()
删除项目
在Treeview控件中可以使用delete()方法删除所选的项目,实例:
样例:删除所选的项目,这个程序在建立Treeview控件时设置selectmode=EXTENDED,相当于一次
可以选择多项,第二个选项在单击鼠标时可以同时按Ctrl键,可以选择不连续的选项。如果
第二个选项在单击鼠标时同时按Shift键,可以选择连续的选项。这个程序下方有Remove按钮,
单击此按钮可以删除所选项目。
from tkinter import *
from tkinter.ttk import *
def removeItem():
iids=tree.selection()
for iid in iids:
tree.delete(iid)
root=Tk()
root.title("ch18_10")
stateCity={"伊利诺":"芝加哥","加州":"洛杉矶",
"德州":"休斯顿","华盛顿州":"西雅图",
"江苏":"南京","山东":"青岛",
"广东":"广州","福建":"厦门"}
tree=Treeview(root,columns=("cities"),selectmode=EXTENDED)
tree.heading("#0",text="State")
tree.heading("cities",text="City")
tree.column("cities",anchor=CENTER)
for state in stateCity.keys():
tree.insert("",index=END,text=state,values=stateCity[state])
tree.pack()
rmBtn=Button(root,text="Remove",command=removeItem)
rmBtn.pack(pady=5)
root.mainloop()
插入项目
在使用Treeview控件时,另一个常用功能是插入项目。插入的方式与建立控件的插入方法insert()
是一样的。至于所插入的内容则可以使用tkinter的Entry控件。
样例:增加设计插入功能,由于这个Treeview控件包含图标栏下共有两个栏位,所以若是想要
插入必须建立两个Entry控件。由于我们必须标出所插入的控件,所以必须在Entry旁加上两个
标签。另外,在执行插入时必须使用一个按钮表示出执行插入操作,所以必须另外创建一个按钮。
from tkinter import *
from tkinter.ttk import *
def removeItem():
iids=tree.selection()
for iid in iids:
tree.delete(iid)
def insertItem():
state=stateEntry.get()
city=cityEntry.get()
if (len(state.strip())==0 or len(city.strip())==0):
return
tree.insert("",END,text=state,values=(city))
stateEntry.delete(0,END)
cityEntry.delete(0,END)
root=Tk()
root.title("ch18_11")
stateCity={"伊利诺":"芝加哥","加州":"洛杉矶",
"德州":"休斯顿","华盛顿州":"西雅图",
"江苏":"南京","山东":"青岛",
"广东":"广州","福建":"厦门"}
root.rowconfigure(1,weight=1)
root.columnconfigure(1,weight=1)
root.columnconfigure(3,weight=1)
stateLab=Label(root,text="State:")
stateLab.grid(row=0,column=0,padx=5,pady=3,sticky=W)
stateEntry=Entry()
stateEntry.grid(row=0,column=1,sticky=W+E,padx=5,pady=3)
cityLab=Label(root,text="City:")
cityLab.grid(row=0,column=2,sticky=E)
cityEntry=Entry()
cityEntry.grid(row=0,column=3,sticky=W+E,padx=5,pady=3)
inBtn=Button(root,text="插入",command=insertItem)
inBtn.grid(row=0,column=4,padx=5,pady=3)
tree=Treeview(root,columns=("cities"),selectmode=EXTENDED)
tree.heading("#0",text="State")
tree.heading("cities",text="City")
tree.column("cities",anchor=CENTER)
for state in stateCity.keys():
tree.insert("",index=END,text=state,values=stateCity[state])
tree.grid(row=1,column=0,columnspan=5,sticky=W+E+N+S)
rmBtn=Button(root,text="Remove",command=removeItem)
rmBtn.grid(row=2,column=2,padx=5,pady=3,sticky=W)
root.mainloop()
讲解:rowconfigure()方法的第一个参数是1,代表row=1,相当于让row=1的Treeview
控件随着窗口缩放,缩放比由第二个参数weight=1得知是1:1缩放。columnconfigure()方法
的第一个参数是1,代表column=1,相当于让column=1的stateEntry控件随着窗口缩放,缩放
比由第二个参数weight=1得知是1:1缩放。columnconfigure()方法内的第一个参数是3,代表
column=3,相当于让column=3的cityEntry控件随着窗口缩放,缩放比由第二个参数weight=1
得知是1:1缩放。如果没有上述设置,当缩放窗口时,所有组件大小将不会更改。
双击某个项目
在使用Treeview控件时,常常需要执行双击操作,最常见的是打开文档。在Treeview控件中
当发生双击时,会产生<Double-1>事件,我们可以利用这个功能建立一个双击的事件处理程序。
样例:当双击Treeview控件中的某个项目时,会出现对话框,列出所选的项目。
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import *
def doubleClick(event):
e=event.widget
iid=e.identify("item",event.x,event.y)
state=e.item(iid,"text")
city=e.item(iid,"values")[0]
str="{0}:{1}".format(state,city)
messagebox.showinfo("Double Clicked",str)
root=Tk()
root.title("ch18_12")
stateCity={"伊利诺":"芝加哥","加州":"洛杉矶",
"德州":"休斯顿","华盛顿州":"西雅图",
"江苏":"南京","山东":"青岛",
"广东":"广州","福建":"厦门"}
tree=Treeview(root,columns=("cities"),selectmode=EXTENDED)
tree.heading("#0",text="State")
tree.heading("cities",text="City")
tree.column("cities",anchor=CENTER)
for state in stateCity.keys():
tree.insert("",index=END,text=state,values=stateCity[state])
tree.bind("<Double-1>",doubleClick)
tree.pack()
root.mainloop()
讲解:identify("xxx",event.x,event.y)
第一个参数xxx可以是item、column、row,分别使用双击时的坐标,取得双击时的
item、column或row的信息,此例是使用item,所以我们可以由此获得是哪一个项目被
双击。
Treeview绑定滚动条
样例:将滚动条应用在Treeview控件中。
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import *
def doubleClick(event):
e=event.widget
iid=e.identify("item",event.x,event.y)
state=e.item(iid,"text")
city=e.item(iid,"values")[0]
str="{0}:{1}".format(state,city)
messagebox.showinfo("Double Clicked",str)
root=Tk()
root.title("ch18_12")
stateCity={"伊利诺":"芝加哥","加州":"洛杉矶",
"德州":"休斯顿","华盛顿州":"西雅图",
"江苏":"南京","山东":"青岛",
"广东":"广州","福建":"厦门"}
tree=Treeview(root,columns=("cities"),selectmode=EXTENDED)
yscrollbar=Scrollbar(root)
yscrollbar.pack(side=RIGHT,fill=Y)
tree.pack()
yscrollbar.config(command=tree.yview)
tree.configure(yscrollcommand=yscrollbar.set)
tree.heading("#0",text="State")
tree.heading("cities",text="City")
tree.column("cities",anchor=CENTER)
for state in stateCity.keys():
tree.insert("",index=END,text=state,values=stateCity[state])
tree.pack()
root.mainloop()
排序
在创建Treeview控件后,由一个很常见的功能是将栏目信息做排序,通常可以单击栏位标题就
可以执行排序。
样例:排序Treeview控件State栏的数据,在这个程序中为了简化程序,省略了图标栏。
所以Treeview控件只有一个State栏,当单击栏标题时可以正常排序,如果再单击时可以
反向排序,排序方式将如此切换。
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import *
def treeview_sortColumn(col):
global reverseFlag
lst=[(tree.set(st,col),st)
for st in tree.get_children("")]
print(lst)
lst.sort(reverse=reverseFlag)
print(lst)
for index,item in enumerate(lst):
tree.move(item[1],"",index)
reverseFlag= not reverseFlag
root=Tk()
root.title("ch18_12")
reverseFlag=False
myStates={1,2,3,4,5,6,7,8}
tree=Treeview(root,columns=("states"),show="headings")
yscrollbar=Scrollbar(root)
yscrollbar.pack(side=RIGHT,fill=Y)
tree.pack()
yscrollbar.config(command=tree.yview)
tree.configure(yscrollcommand=yscrollbar.set)
tree.heading("states",text="State")
for state in myStates:
tree.insert("",index=END,text=state,values=(state,))
tree.heading("#1",text="State",
command=lambda c="states":treeview_sortColumn(c))
root.mainloop()
讲解:heading()方法,当用鼠标单击标题栏时会执行command所指定的方法,这是
Lambda表达式,将"states"设置给变量c,然后将c当作参数传递给treeview_sortColumn()方法。
get_children([item])
它会传回item的一个tuple的iid值,如果省略则是得到一个tuple,此tuple是top-level的iid值。
move()方法:
move(iid,parent,index)
将iid所指项目移至parent层次的index位置,此程序用""代表parent层次
网友评论