Python GUI编程入门(31)-Treeview控件

Python 专栏收录该内容
11 篇文章 1 订阅

Treeview是Tkinter8.5新引入的控件,可以用于实现较为复杂的GUI界面。本文使用一个FileBrowser实例来说明它的用法。

构建主窗口和退出菜单的代码和前一篇文章几乎相同:

 

root = Tk()root.title('Tkinter Treeview and PanedWindow Demo V1.0')root.grid_rowconfigure(0, weight=1)root.grid_columnconfigure(0, weight=1)
screen_w = root.winfo_screenwidth()screen_h = root.winfo_screenheight()root.maxsize(width=screen_w, height=screen_h)rw = int(screen_w / 2)rh = int(screen_h / 2)root.geometry('{}x{}+{:g}+{:g}'.format(rw, rh, rw / 2, rh / 2))
top_menu = Menu(root)root.config(menu=top_menu)
file_menu = Menu(top_menu, tearoff=False)top_menu.add_cascade(label='File', menu=file_menu)file_menu.add_command(label="Exit", command=root.quit)
 

构建一个水平方向的PanedWindow控件,grid布局时sticky属性设置为四面填充。

 

paned_window = PanedWindow(root, orient=HORIZONTAL)paned_window.grid(row=0, column=0, sticky='eswn')

构建管理左侧控件的Frame对象:

 

tree_area = Frame(paned_window)tree_area.grid_rowconfigure(0, weight=1)tree_area.grid_columnconfigure(0, weight=1)paned_window.add(tree_area)
 

准备Treeview图标文件:

 

cur_path = os.path.abspath(os.path.dirname(__file__))pc_image = PhotoImage(file=cur_path + '\\images\\pc.png')drive_image = PhotoImage(file=cur_path + '\\images\\drive.png')folder_image = PhotoImage(file=cur_path + '\\images\\folder.png')file_image = PhotoImage(file=cur_path + '\\images\\file.png')
 

构建Treeview控件。将show属性指定为'tree'可以消除顶部的标题行。

 

tree_view = Treeview(tree_area, show='tree', selectmode='browse')tree_view.grid(row=0, column=0, sticky='nsew')
 

添加水平和垂直滚动条:

 

scroll_ty = Scrollbar(tree_area, orient=VERTICAL, command=tree_view.yview)scroll_ty.grid(row=0, column=1, sticky=N+S)tree_view['yscrollcommand']=scroll_ty.set
scroll_tx = Scrollbar(tree_area, orient=HORIZONTAL, command=tree_view.xview)scroll_tx.grid(row=1, column=0, sticky=E+W)tree_view['xscrollcommand']=scroll_tx.set
 

增加根节点及驱动器节点:

 

pc_node= tree_view.insert('', 'end',                          text=os.environ.get('COMPUTERNAME'),                          image=pc_image,                          open=False)for c in string.ascii_uppercase:    disk = c + ':'    if os.path.isdir(disk):        drive_node = tree_view.insert(pc_node, 'end', text=disk, image=drive_image)
 

给定节点,获得节点路径的函数:

 

 

def node_path(node):    path = ''    parent = node    while parent:        node_text = tree_view.item(parent, 'text')        if len(path) > 0:            path = os.path.join(node_text, path)        else:            path = node_text        parent = tree_view.parent(parent)    return path
 

由于磁盘目录的结构一般都会非常复杂,因此本示例采用以下策略:

  1. 展开节点时才会读入下级节点目录结构

  2. 关闭节点时删除下级节点的目录结构

 

 

def open_node(event):    focus = tree_view.focus()    for node in tree_view.get_children(focus):        insert_child_items(node)
tree_view.bind('<<TreeviewOpen>>', open_node)
def close_node(event):    focus = tree_view.focus()    for node in tree_view.get_children(focus):        children = tree_view.get_children(node)        for c in children:            tree_view.delete(c)
tree_view.bind('<<TreeviewClose>>', close_node)

insert_child_items的实现如下:

 

def insert_child_items(parent_node):    path = node_path(parent_node)    if os.path.isdir(path):        try:            dir_items = os.scandir(path)            for item in dir_items:                if item.is_dir() and ('.$'.find(item.name[0])<0):                    tree_view.insert(parent_node, 'end', text=item.name, image=folder_image)        except Exception as e:            print(e)

增加下级节点的子节点操作以目录为操作对象。这个操作还会排除系统文件和隐藏文件。异常处理的对象是没有访问权限等情况。

构建右侧显示区域:

 

detail_area = Frame(paned_window)detail_area.grid_rowconfigure(0, weight=1)detail_area.grid_columnconfigure(0, weight=1)paned_window.add(detail_area)
 

构建列表形式的Treeview:

 

list_view = Treeview(detail_area)list_view['columns'] = ('#1', '#2', "#3", '#4')list_view.column("#0", width=150, minwidth=150, stretch=YES)list_view.column("#1", width=150, minwidth=150, stretch=YES)list_view.column("#2", width=100, minwidth=100, stretch=YES)list_view.column("#3", width=100, minwidth=100, stretch=NO)list_view.column("#4", width=100, minwidth=50, stretch=YES)
list_view.heading("#0", text="Name", anchor=W)list_view.heading("#1", text="Date modified", anchor=W)list_view.heading("#2", text="Type", anchor=W)list_view.heading("#3", text="Size", anchor=W)
list_view.grid(row=0, column=0, sticky='nsew')

构建Scrollbar和Sizegrip控件:

 

scroll_fy = Scrollbar(detail_area, orient=VERTICAL, command=list_view.yview)scroll_fy.grid(row=0, column=1, sticky=N+S)list_view['yscrollcommand']=scroll_fy.set
scroll_fx = Scrollbar(detail_area, orient=HORIZONTAL, command=list_view.xview)scroll_fx.grid(row=1, column=0, sticky=E+W)list_view['xscrollcommand']=scroll_fx.set
Sizegrip(detail_area).grid(row=1, column=1)

当左侧Treeview的被选节点发生变化时,获取对应目录中的文件并表示在右侧列表形式的Treeview中。

 

 

def select_node(event):    children = list_view.get_children('')    for c in children:        list_view.delete(c)    focus = tree_view.focus()    path = node_path(focus)    if os.path.isdir(path):        try:            dir_items = os.scandir(path)            iid = 0            for item in dir_items:                if item.is_file() and ('.$'.find(item.name[0]) < 0):                    stat_info = os.stat(item.path)                    m_time = time.strftime("%Y/%m/%d %H:%M", time.localtime(stat_info.st_mtime))                    type = ' File'                    dot_pos = item.name.rfind('.')                    if dot_pos > 0:                        type = item.name[dot_pos+1:].upper() + type                    list_view.insert('', 'end', str(iid), text=item.name, values=(m_time, type, stat_info.st_size))                    iid += 1        except Exception as e:            print(e)
tree_view.bind('<<TreeviewSelect>>', select_node)

软件的演示视频如下:

视频链接

 

完整代码可以从以下地址下载:

https://github.com/xueweiguo/TkinterPrimer/blob/master/Sample/31%20FileBrowser.py

觉得本文有帮助?请分享给更多人。

阅读更多更新文章,请关注微信公众号【面向对象思考】

  • 6
    点赞
  • 0
    评论
  • 40
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值