Tkinter库的学习记录18-Treeview

Tkinter库的学习记录18-Treeview
18、TreeviewTreeview是tkinter.ttk的控件这个控件主要是提供多栏的显示功能我们可以称其为树状表格数据(Treeview)。在设计时也可以在左边栏设计成树状结构或是称层次结构用户可以显示或隐藏任何部分这个最左边的栏称为图标栏。18-1 Treeview的基本概念设计Treeview控件的基本思想是使用Treeview构造方法建立Treeview对象。它的语法如下。Treeview(父对象,options, ...)参数一父对象表示建立在哪一个父对象内。options(1) columns栏位的字符串其中第一个栏位是图标栏是默认的不在此设置范围如果设置columns(Name, Age)则控件有三栏首先是最左栏的图标栏可以进行展开(expand)或是隐藏(collapse)操作另外两栏是Name和Age。(2) cursor可以设置光标在此控件上的外观。(3) displaycolumns可以设置栏位显示顺序。①如果参数是“#all”表示显示所有栏同时依建立顺序显示。②如果设置columns(Name, Age, Date)使用insert()插入元素时需要依次插入元素。同样状况如果使用columns(2.0)(2.0)是指实体索引则图标栏在最前面紧跟着是Date栏然后是Name栏。这种状况也可以写成columns(Date, Name)。(4) height控件每行的高度。(5) padding可以使用1 ~ 4个参数设置内容与控件框的间距它的规则如下。值LeftTopRightBottomaaaaaababababcacbcabcdabcd(6) selectmode用户可以使用鼠标选择项目的方式。①selectmodeBROWSE一次选择一项这是默认。②selectmodeEXTENDED一次可以选择多项。③selectmodeNONE无法用鼠标执行选择。(7) show默认是设置显示图标栏的标签showtree如果省略则是显示图标栏如果设为showheadings则不显示图标栏。(8) takefocus默认是True如果不想被访问可以设为False。下面以实例说明更多规则。程序实例ch18_1简单建立Treeview控件的应用。from tkinter import * from tkinter.ttk import * root Tk() root.title(ch18_1) # 建立Treeview tree Treeview(root, columns(cities)) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(#1, textCity) # 建立内容 tree.insert(, indexEND, text伊利诺, values芝加哥) tree.insert(, indexEND, text加州, values洛杉矶) tree.insert(, indexEND, text江苏, values南京) tree.pack() root.mainloop()执行结果 建议单击选择以体会Treeview的基本操作下方右图是单击选择的示范输出。上述程序第8行建立Treeview控件此控件名称是tree此控件有一个栏位域名是cities未来程序设计可以使用此cities代表这一个栏位。经这样设置后我们可以知道此多栏窗体有两个栏位除了cities外另外左边有图标栏位。程序第10、11行使用heading()方法在这个方法内建立了栏标题其中第一个参数#0 是指最左栏图标栏位#1 是指第一个栏位所以这两行分别建立了两个栏标题。程序第14 ~ 16行使用insert()方法插入Treeview控件内容在这个方法中的第一个参数代表父id因为图标栏未来可能有树状结构所以有这一个栏位设计后面会由实例说明。当所建的栏是最顶层时可以用空字符串处理。第二个参数indexEND代表将资料插入Treeview末端它的思想与Text控件的END相同。第三个参数text是设置图标栏的内容。第4个参数的values是设置City栏的内容。程序实例ch18_1_1重新设计ch18_1再建立Treeview控件时增加showheadings参数将不显示图标栏。tree Treeview(root, columns(cities), showheadings)执行结果程序实例ch18_2程序实例ch18_1.py第8行columns(cities)指出栏标题名称时cities我们可以使用此字符串代表栏位。在第11行使用#1代表cities栏其实可以使用此cities取代#1。tree.heading(cities, textCity)执行结果与ch18_1相同。在程序实例ch18_1.py的第13行insert()方法中第4个参数values是设置所插入的内容上述由于除了图标栏外只有一个栏位所以只是设置values等于字符串内容如果有多栏时须使用values(value1, value2, ...)如果所设置的内容数太少时其他栏将是空白如果所设置的内容数太多时多出来的内容将被抛弃。程序实例ch18_3扩充设计ch18_1增加population人口数栏位其中人口数的单位是万人。from tkinter import * from tkinter.ttk import * root Tk() root.title(ch18_3) # 建立Treeview tree Treeview(root, columns(cities, population)) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(#1, textCity) tree.heading(#2, textPopulations) # 建立内容 tree.insert(, indexEND, text伊利诺, values(芝加哥, 800)) tree.insert(, indexEND, text加州, values(洛杉矶, 1000)) tree.insert(, indexEND, text江苏, values(南京, 900)) tree.pack() root.mainloop()执行结果由上述执行结果下面在此强调insert()方法的用法。(1) text设置图标栏的内容。(2) values设置一般栏位的内容values (芝加哥, 800)这是以顺序方式设置栏位”芝加哥“是第一个栏位 ”800“是第二个栏位。其实当我们了解上述values参数内容后也可以将Python的列表应用于建立栏位内容。程序实例ch18_3_1重新设计ch18_3使用列表方式建立栏位内容大家应该学习第7 ~ 9行设置列表内容以及第17 ~ 19行将列表应用在insert()方法的values参数。from tkinter import * from tkinter.ttk import * root Tk() root.title(ch18_3_1) list1 [芝加哥, 800] # 以列表方式设置栏内容 list2 [洛杉矶, 1000] list3 [南京, 900] # 建立Treeview tree Treeview(root, columns(cities, population)) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(#1, textCity) tree.heading(#2, textPopulations) # 建立内容 tree.insert(, indexEND, text伊利诺, valueslist1) tree.insert(, indexEND, text加州, valueslist2) tree.insert(, indexEND, text江苏, valueslist3) tree.pack() root.mainloop()执行结果与ch18_3相同。上述程序使用列表建立insert()方法的values参数内容也可以使用元组代替具有相同效果。18-2 格式化Treeview栏位内容Treeview控件的column()方法主要用于格式化特定栏位的内容它的语法格式如下。cplumn(id, options)其中id是指出特定栏位可以用字符串表达或是用#index索引方式。下列是options的可能参数。(1) anchor可以设置栏内容参考位置。(2) minwidth最小栏宽默认是20像素。(3) stretch默认是1当控件大小改变时栏宽将随着改变。(4) width默认栏宽是200像素。如果使用此方法不含参数如下所示。ret column(id)将以字典方式传回特定栏所有参数的内容。程序实例ch18_4格式化ch18_3将第1、2栏宽度改为150同时居中对齐图标栏则不改变。from tkinter import * from tkinter.ttk import * root Tk() root.title(ch18_4) # 建立Treeview tree Treeview(root, columns(cities, population)) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(#1, textCity) tree.heading(#2, textPopulations) # 格式化栏位 tree.column(#1, anchorCENTER, width150) tree.column(#2, anchorCENTER, width150) # 建立内容 tree.insert(, indexEND, text伊利诺, values(芝加哥, 800)) tree.insert(, indexEND, text加州, values(洛杉矶, 1000)) tree.insert(, indexEND, text江苏, values(南京, 900)) tree.pack() root.mainloop()执行结果程序实例ch18_5扩充设计ch18_4以字典方式列出cities栏位的所有内容这个程序只增加下列两行。cityDict tree.column(cities) print(cityDict)执行结果 下面是Python shell窗口的执行结果PS E:\code\python\GuiTkinter\ch18 python .\ch18.py {width: 150, minwidth: 20, stretch: 1, anchor: center, id: cities}18-3 建立不同颜色的行内容建立Treeview控件内容时常常会需要在不同行之间用不同底色作区分以方便使用者查看若是想要设计这方面的程序可以使用Text控件的标签。Treeview控件由tag_configure()方法可以使用使用这个方法建立标签然后定义此标签的格式可参考下列指令。tag_configure(tagName, options, ...)上述第一个参数tagName是标签名称可以用此名称将此标签导入栏位数据。options的可能参数如下。(1) background标签背景颜色。(2) font字形设置。(3) foreground标签前景颜色。(4) image图像与列表同时显示。要将标签导入栏位使用的是insert()方法这时需在此方法内增加tags参数设置如下所示。insert(..., tagstagName)在企业实际应用中数据量通常很庞大这时无法使用单笔数据一步一步建立Treeview控件内容适度使用python的数据结构与遍历方法可以让程序变得有效率。在下列程序实例中使用字典存储数据然后将此字典以循环方式导入Treeview控件内。程序实例ch18_6基本上是ch18_2的扩充在这个实例中将偶数行使用蓝色底显示。from tkinter import * from tkinter.ttk import * root Tk() root.title(ch18_6) stateCity {伊利诺: 芝加哥, 加州: 洛杉矶, 德州: 休斯顿, 华盛顿州: 西雅图, 江苏: 南京, 山东: 青岛, 广东: 广州, 福建: 厦门} # 建立Treeview tree Treeview(root, columns(cities)) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(cities, textCity) # 格式化栏位 tree.column(cities, anchorCENTER) # 建立内容行号从1算起偶数行是用浅蓝色底 tree.tag_configure(evenColor, backgroundlightblue) # 设置标签 rowCount 1 # 行号从1算起 for state in stateCity.keys(): if (rowCount % 2 1): tree.insert(, indexEND, textstate, valuesstateCity[state]) else: tree.insert(, indexEND, textstate, valuesstateCity[state], tags[evenColor]) rowCount 1 tree.pack() root.mainloop()执行结果18-4 建立层级式的Treeview层级式(Hierarchy)的相关知识在前几节已经介绍过只要在图标栏先建立top-level的项目id然后将相关子项目放在所属的top-level项目id即可。程序实例ch18_7建立层级式的Treeview控件内容。from tkinter import * from tkinter.ttk import * root Tk() root.title(ch18_7) asia {中国: 北京, 日本: 东京, 泰国: 曼谷, 韩国: 首尔} euro {英国: 伦敦, 法国: 巴黎, 德国: 柏林, 意大利: 罗马} # 建立Treeview tree Treeview(root, columns(capital)) # 建立栏标题 tree.heading(#0, text国家) # 图标栏 tree.heading(capital, text首都) # 建立id idAsia tree.insert(, indexEND, textAsia) idEuro tree.insert(, indexEND, textEurope) # 建立idAsia底下内容 for country in asia.keys(): tree.insert(idAsia, indexEND, textcountry, values(asia[country])) # 建立idEuro底下内容 for country in euro.keys(): tree.insert(idEuro, indexEND, textcountry, values(euro[country])) tree.pack() root.mainloop()执行结果在上述程序第7、8行是建立亚洲asia和欧洲euro国家与首都的字典数据。第16、17行则是建立图标栏top-level的id分别是idAsia和idEuro。建立层级式数据最关键的是使用insert()方法时必须在第一个参数设置top-level的id第19、20是建立亚洲国家国名与首都数据所以第20行的insert()方法的第一个参数是idAsia这表示插入的数据放在idAsia层级下程序代码设计如下。tree.insert(idAsia, ...)第22、23行是建立欧洲国家原理同上。18-5 插入图像在insert()方法内若是增加image参数可以添加图像在添加图像时需要考虑的是可能row的高度不足所以必须增加高度。这时可以用下列Style()方法处理。Style().configure(Treeview, rowheightxx) # xx是高度设置程序实例ch18_8设计一个含有图像的Treeview。from tkinter import * from tkinter.ttk import * from PIL import Image, ImageTk root Tk() root.title(ch18_8) Style().configure(Treeview, rowheight35) # 格式化扩充row高度 info [凤凰新闻APP可以获得中国各地最新消息, 瑞士国家铁路APP提供全瑞士火车时刻表, 可口可乐APP是全球最畅销的饮料品牌] # 建立Treeview tree Treeview(root, columns(说明)) tree.heading(#0, textApp) # 图标栏位icon column tree.heading(#1, text功能说明) tree.column(#1, width300) # 格式化扩充column宽度 imag1 Image.open(news.jpg) # 插入凤凰新闻App图示 imgObj1 ImageTk.PhotoImage(imag1) tree.insert(, indexEND, text凤凰新闻, imageimgObj1, valuesinfo[0]) imag2 Image.open(train.jpg) # 插入瑞士国家铁路App图示 imgObj2 ImageTk.PhotoImage(imag2) tree.insert(, indexEND, text瑞士铁路, imageimgObj2, valuesinfo[1]) imag3 Image.open(coke.jpg) # 插入可口可乐App图示 imgObj3 ImageTk.PhotoImage(imag3) tree.insert(, indexEND, text可口可乐, imageimgObj3, valuesinfo[2]) tree.pack() root.mainloop()执行结果 上述程序如果没有增加第8行将看到下方左图的结果。18-6 Selection选项发生与事件触发在18-1节曾由说明在Treeview控件中可以由三种选择模式分别是BROWSE默认、EXTENDED、NONE这是使用selectmode参数设置的当有新选组项目发生时会产生虚拟事件其实我们可以针对此特性设计相关功能。程序实例ch18_9使用默认的BROWSE选项一次只能选择一个项目当选择发生时将同步在窗口下方的状态栏显示所选择的项目。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] # 取得第0索引栏位内容 str {0} : {1}.format(col1, col2) # 取得所选项目内容 var.set(str) # 设置状态栏内容 root Tk() root.title(ch18_9) stateCity {伊利诺: 芝加哥, 加州: 洛杉矶, 德州: 休斯顿, 华盛顿州: 西雅图, 江苏: 南京, 山东: 青岛, 广东: 广州, 福建: 厦门} # 建立Treeview tree Treeview(root, columns(cities), selectmodeBROWSE) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(cities, textCity) # 格式化栏位 tree.column(cities, anchorCENTER) # 建立内容行号从1算起偶数行是用浅蓝色底 tree.tag_configure(evenColor, backgroundlightblue) # 设置标签 rowCount 1 # 行号从1算起 for state in stateCity.keys(): if (rowCount % 2 1): tree.insert(, indexEND, textstate, valuesstateCity[state]) else: tree.insert(, indexEND, textstate, valuesstateCity[state], tags[evenColor]) rowCount 1 tree.bind(TreeviewSelect, treeSelect) # Treeview控件Select事件发生 tree.pack() var StringVar() label Label(root, textvariablevar, reliefgroove) # 建立状态栏 label.pack(fillBOTH, expandTrue) root.mainloop()执行结果上述第19行在建立Treeview控件对象时特别设置selectmodeBROWSE参数只是特别强调这个模式因为这是默认模式所以如果省略此设置也将获得一样的结果。程序第35行是将有选择项目发生时交由treeSelect()事件处理程序处理。第4行是取得窗口内发生此事件的控件设置给widgetObj。第5行是Treeview控件对象WidgetObj调用selection()方法目的是取得目前所选的项目用itemselected代表通常也可称此所选的项目是iid这是tkinter内部使用的id。第6、7行则是由控件对象widgetObj调用item()方法注意这里需要两个参数目的是取得所选项目的图标栏内容和索引栏内容。第8行是格式化所获得的内容第9行则是将内容设置到状态栏。18-7 删除项目在Treeview控件中可以使用delete()方法删除所选的项目下面将以实例说明。程序实例ch18_10删除所选的项目这个程序在建立Treeview控件时设置selectmodeEXTENDED相当于一次可以选择多项第二个选项在单击鼠标时可以同时按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 {伊利诺: 芝加哥, 加州: 洛杉矶, 德州: 休斯顿, 华盛顿州: 西雅图, 江苏: 南京, 山东: 青岛, 广东: 广州, 福建: 厦门} # 建立Treeview tree Treeview(root, columns(cities), selectmodeEXTENDED) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(cities, textCity) # 格式化栏位 tree.column(cities, anchorCENTER) # 建立内容 for state in stateCity.keys(): tree.insert(, indexEND, textstate, valuesstateCity[state]) tree.pack() rmBtn Button(root, textRemove, commandremoveItem) # 删除按钮 rmBtn.pack(pady5) root.mainloop()执行结果上述程序当单击Remove按钮时会执行第3 ~ 6行的removeItem()方法这时会先执行第4行如下所示。iids tree.selection()上述方法会将目前选项传给iidsiids的数据类型是元组所以第5、6行是循环可以遍历此元组然后依次删除所选的项目。18-8 插入项目在使用Treeview控件时除了18-7节的删除控件项目外另一个常用功能是插入项目。插入的方式与建立控件的插入方法insert()是一样的。至于所插入的内容则可以使用tkinter的Entry控件。下面将用实例说明。程序实例ch18_11扩充程序实例ch18_10增加设计插入功能由于这个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() # 获取stateEntry的插入 city cityEntry.get() # 获取cityEntry的插入 # 如果输入数据不完全不往下执行 if (len(state.strip()) 0 or len(city.strip()) 0): return tree.insert(, end, textstate, valuescity) stateEntry.delete(0, END) # 清空stateEntry cityEntry.delete(0, END) # 清空cityEntry root Tk() root.title(ch18_11) stateCity {伊利诺: 芝加哥, 加州: 洛杉矶, 德州: 休斯顿, 华盛顿州: 西雅图, 江苏: 南京, 山东: 青岛, 广东: 广州, 福建: 厦门} # 以下三行主要是应用在缩放窗口 root.rowconfigure(1, weight1) # row1会随窗口缩放1:1变化 root.columnconfigure(1, weight1) # column1会随窗口缩放1:1变化 root.columnconfigure(3, weight1) # column3会随窗口缩放1:1变化 stateLab Label(root, textState: ) # 建立State标签 stateLab.grid(row0, column0, padx5, pady3, stickyW) stateEntry Entry() # 建立State文本框 stateEntry.grid(row0, column1, padx5, pady3, stickyEW) cityLab Label(root, textCity: ) # 建立City标签 cityLab.grid(row0, column2, stickyE) cityEntry Entry() # 建立City文本框 cityEntry.grid(row0, column3, padx5, pady3, stickyEW) # 建立Inset按钮 inBtn Button(root, text插入, commandinsertItem) inBtn.grid(row0, column4, padx5, pady3) # 建立Treeview tree Treeview(root, columns(cities), selectmodeEXTENDED) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(cities, textCity) # 格式化栏位 tree.column(cities, anchorCENTER) # 建立内容 for state in stateCity.keys(): tree.insert(, indexEND, textstate, valuesstateCity[state]) tree.grid(row1, column0, columnspan5, padx5, stickyNSEW) rmBtn Button(root, text删除, commandremoveItem) # 删除按钮 rmBtn.grid(row2, column2, padx5, pady3, stickyW) root.mainloop()执行结果若单击“插入”按钮将得到下列结果。上述程序第25 ~ 27行主要是处理缩放窗口时Treeview的变化第25行的rowconfigure()方法内的第一个参数是1代表row1相当于让row1的Treeview控件随着窗口缩放缩放比由第二个参数weight1得知是11缩放。第26行的columnconfigure()方法内第一个参数是1代表column1相当于让column1的stateEntry控件随着窗口缩放缩放比由第二个参数weight1得知是11缩放。第27行的的columnconfigure()方法内第一个参数是3代表column3相当于让column3的cityEntry控件随着窗口缩放缩放比由第二个参数weight1得知是11缩放。如果没有上述设置当缩放窗口时所有组件大小将不会更改。第38、39是创建“插入”按钮当单击此按钮时会执行第7 ~ 15行insertItem()方法。在这个方法中第8行是读取stateEntry的输入第9行是读取cityEntry的输入。第11、12行是判断是否两栏中皆有输入如果有一个栏中没有输入则返回不往下执行。第13行是插入stateEntry和cityEntry的输入。由于插入已经完成所以第14行删除stateEntry文本框内容第15行删除cityEntry文本框内容。18-9 双击某个项目在使用Treeview控件时常常需要执行双击操作最常见的是打开文档。本节将讲解这方面的知识。在Treeview控件中当发生双击时会产生事件我们可以利用这个功能建立一个双击的事件处理程序。对于这类问题另一个重点是取得双击的项目下面将以实例讲解。程序实例ch18_12当双击Treeview控件中的某个项目时会出现对话框列出所选的项目。from tkinter import * from tkinter.ttk import * from tkinter import messagebox 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 {伊利诺: 芝加哥, 加州: 洛杉矶, 德州: 休斯顿, 华盛顿州: 西雅图, 江苏: 南京, 山东: 青岛, 广东: 广州, 福建: 厦门} # 建立Treeview tree Treeview(root, columns(cities), selectmodeEXTENDED) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(cities, textCity) # 格式化栏位 tree.column(cities, anchorCENTER) # 建立内容 for state in stateCity.keys(): tree.insert(, indexEND, textstate, valuesstateCity[state]) tree.bind(Double-1, doubleClick) tree.pack() root.mainloop()执行结果上述程序第30行将双击操作与doubleClick()方法绑定所以当双击时会执行第4 ~ 10行的doubleClick()方法。第5行是取得双击事件的控件当6行identify()方法的用法如下。identify(xxx, event.x, event.y)第一个参数xxx可以是item、column、row分别是使用双击时的坐标取得双击时的item、column或row的信息此例是使用item所以我们可以由此获得是哪一个项目被双击。第7行是获得双击的“text”信息此信息是State内容。第8行是获得双击的“value”信息此信息是City内容。第8行是获得格式化的字符串第10行是出现showinfo的消息对话框。18-10 Treeview绑定滚动条在12-8节有说明过滚动条Scrollbar的用法同时也将Scrollbar与Listbox进行了结合。17-3节则是介绍了将Text加上滚动条的设计。我们可以参考这两节的思路将Scrollbar应用在Treeview控件中。程序实例ch18_13将滚动条应用在Treeview控件中。from tkinter import * from tkinter.ttk import * root Tk() root.title(ch18_13) stateCity {伊利诺: 芝加哥, 加州: 洛杉矶, 德州: 休斯顿, 华盛顿州: 西雅图, 江苏: 南京, 山东: 青岛, 广东: 广州, 福建: 厦门, 浙江: 杭州, 安徽: 合肥, 北京: 北京, 上海: 上海, 天津: 天津, 四川: 成都 } tree Treeview(root, columns(cities), selectmodeEXTENDED) yscrollbar Scrollbar(root) # y轴scrollbar对象 yscrollbar.pack(sideRIGHT, fillY) # y轴scrollbar包装显示 tree.pack() yscrollbar.config(commandtree.yview) # 将y轴scrollbar与treeview绑定 tree.configure(yscrollcommandyscrollbar.set) # 建立栏标题 tree.heading(#0, textState) # 图标栏 tree.heading(cities, textCity) # 格式化栏位 tree.column(cities, anchorCENTER) # 建立内容 for state in stateCity.keys(): tree.insert(, indexEND, textstate, valuesstateCity[state]) root.mainloop()执行结果18- 11 排序在创建Treeview控件后有一个很常见的功能是将栏目信息做排序通常是可以单击栏位标题就可以执行排序本节将以实例讲解这方面的应用。程序实例ch18_14排序Treeview控件State栏的数据在这个程序中为了简化程序省略了图标栏。所以Treeview控件只有一个State栏当单击栏标题时可以正常排序(由小到大)如果再单击可以反向排序排序方式将如此切换。from tkinter import * from tkinter.ttk import * def treeview_sortColumn(col): global reverserFlag # 定义排序标识全局变量 lst [(tree.set(st, col), st) for st in tree.get_children()] print(lst) # 打印列表 lst.sort(reversereverserFlag) # 排序列表 print(lst) # 打印列表 for index, item in enumerate(lst): # 重新移动项目内容 tree.move(item[1], , index) reverserFlag not reverserFlag # 更改排序标识 root Tk() root.title(ch18_14) reverserFlag False # 排序标识注明是否反向排序 myStates {Illinois, California, Texas, Washington, Jiangsu, shandong, Guangdong, Fujian, Mississippi, Kentucky, Florida, Indiana} tree Treeview(root, columns(states), showheadings) yscrollbar Scrollbar(root) # y轴scrollbar对象 yscrollbar.pack(sideRIGHT, fillY) # y轴scrollbar包装显示 tree.pack() yscrollbar.config(commandtree.yview) # 将y轴scrollbar与treeview绑定 tree.configure(yscrollcommandyscrollbar.set) # 建立栏标题 tree.heading(states, textState) # 图标栏 # 建立内容 for state in myStates: tree.insert(, indexEND, textstate, values(state, )) # 单击标题栏将启动treeview_sortColumn tree.heading(#1, textState, commandlambda cstates: treeview_sortColumn(c)) root.mainloop()执行结果这个程序为了简单省略显示图标栏在第22行创建Treeview控件时增加了showheadings参数。tree Treeview(root, columns(states), showheadings)第31、32行是建立栏位的数据相当于将myState列表数据放入Treeview控件。接下来第34、35行是重点这其实是heading()方法所以是一条命令只是因为太长分为两行撰写.当用鼠标单击标题栏时会执行command所指定的方法这是Lambda表达式将”states“设置给变量c然后将c当作参数传递给treeview_sortColumn()方法。程序第3~12行是treeview_sortColumn()方法在这个方法中为了让读者了解数据内容特别在第7和第9行列出目前列表内容方便了解目前程序的意义。首先第5行设置reverseFlag是全局变量它的原始定义在17行。第5、6行其实是同一条命令如下所示。lst [(tree.set(st, col), st) for st in tree.get_children()]上述有一个get_children()方法它的语法如下。get_children(item)它会传回item的一个tuple的iid值如果省略则是得到一个tuple此tuple是top-level的iid值。上述程序主要是建立lst列表第7行会打印这个列表内容可以在Python Shell窗口看到如下所示。[(Mississippi, I001), (Texas, I002), (Indiana, I003), (California, I004), (Illinois, I005), (Florida, I006), (Guangdong, I007), (Jiangsu, I008), (shandong, I009), (Fujian, I00A), (Washington, I00B), (Kentucky, I00C)] [(California, I004), (Florida, I006), (Fujian, I00A), (Guangdong, I007), (Illinois, I005), (Indiana, I003), (Jiangsu, I008), (Kentucky, I00C), (Mississippi, I001), (Texas, I002), (Washington, I00B), (shandong, I009)]第10、11行内容如下。for index, item in enumerate(lst): # 重新移动项目内容 tree.move(item[1], , index)其中有一个move()方法语法如下。move(iid, parent, index)将iid所指项目移至parent层次的index位置此程序用”“代表parent层次。第12行是更改排序标识这样下次就可以使用反向排序。