使用python和gtkTreeView创建一个简单的文件浏览器

时间:2014-05-02 17:33:01

标签: python treeview gtk gtk3

我正在尝试使用python和GTK3创建一个简单的文件浏览器。受到another question here的启发,我能够做出一个小小的工作实例

#!/usr/bin/python
import os
from gi.repository import Gtk

window = Gtk.Window()
window.connect("delete-event", Gtk.main_quit)


filesystemTreeStore = Gtk.TreeStore(str)
parents = {}

for (path, dirs, files) in os.walk("/home"):
    for subdir in dirs:
        parents[os.path.join(path, subdir)] = filesystemTreeStore.append(parents.get(path, None), [subdir])
    for item in files:
        filesystemTreeStore.append(parents.get(path, None), [item])

filesystemTreeView = Gtk.TreeView(filesystemTreeStore)
renderer = Gtk.CellRendererText()
filesystemColumn = Gtk.TreeViewColumn("Title", renderer, text=0)
filesystemTreeView.append_column(filesystemColumn)

window.add(filesystemTreeView)


window.show_all()
Gtk.main()

代码有效,但结果感觉不太有效。我能够阅读并显示整个linux文件系统,但是花了很长时间。一个原因可能是使用os.walk。

另一件事是,这样的代码不允许打开空目录。

出于这个原因,我想只显示为其制作列表的父目录的内容,并在用户探索树结构时逐渐展开树。

我还没能找到使用Python和GTK3的解决方案。有similar solution但是对于Tkinter

2 个答案:

答案 0 :(得分:3)

我能够找到解决方案。可能有一个更好的解决方案,但我很高兴它按预期工作。我追加“虚拟”节点,使文件夹可扩展,即使是安培。不得不在扩展/折叠treeView时处理添加和删除树内容。

这是我的解决方案:

#!/usr/bin/python
import os, stat
from gi.repository import Gtk
from gi.repository.GdkPixbuf import Pixbuf

def populateFileSystemTreeStore(treeStore, path, parent=None):
    itemCounter = 0
    # iterate over the items in the path
    for item in os.listdir(path):
        # Get the absolute path of the item
        itemFullname = os.path.join(path, item)
        # Extract metadata from the item
        itemMetaData = os.stat(itemFullname)
        # Determine if the item is a folder
        itemIsFolder = stat.S_ISDIR(itemMetaData.st_mode)
        # Generate an icon from the default icon theme
        itemIcon = Gtk.IconTheme.get_default().load_icon("folder" if itemIsFolder else "empty", 22, 0)
        # Append the item to the TreeStore
        currentIter = treeStore.append(parent, [item, itemIcon, itemFullname])
        # add dummy if current item was a folder
        if itemIsFolder: treeStore.append(currentIter, [None, None, None])
        #increment the item counter
        itemCounter += 1
    # add the dummy node back if nothing was inserted before
    if itemCounter < 1: treeStore.append(parent, [None, None, None])

def onRowExpanded(treeView, treeIter, treePath):
    # get the associated model
    treeStore = treeView.get_model()
    # get the full path of the position
    newPath = treeStore.get_value(treeIter, 2)
    # populate the subtree on curent position
    populateFileSystemTreeStore(treeStore, newPath, treeIter)
    # remove the first child (dummy node)
    treeStore.remove(treeStore.iter_children(treeIter))

def onRowCollapsed(treeView, treeIter, treePath):
    # get the associated model
    treeStore = treeView.get_model()
    # get the iterator of the first child
    currentChildIter = treeStore.iter_children(treeIter)
    # loop as long as some childern exist
    while currentChildIter:
        # remove the first child
        treeStore.remove(currentChildIter)
        # refresh the iterator of the next child
        currentChildIter = treeStore.iter_children(treeIter)
    # append dummy node
    treeStore.append(treeIter, [None, None, None])

window = Gtk.Window()
window.connect("delete-event", Gtk.main_quit)

# initialize the filesystem treestore
fileSystemTreeStore = Gtk.TreeStore(str, Pixbuf, str)
# populate the tree store
populateFileSystemTreeStore(fileSystemTreeStore, '/home')
# initialize the TreeView
fileSystemTreeView = Gtk.TreeView(fileSystemTreeStore)

# Create a TreeViewColumn
treeViewCol = Gtk.TreeViewColumn("File")
# Create a column cell to display text
colCellText = Gtk.CellRendererText()
# Create a column cell to display an image
colCellImg = Gtk.CellRendererPixbuf()
# Add the cells to the column
treeViewCol.pack_start(colCellImg, False)
treeViewCol.pack_start(colCellText, True)
# Bind the text cell to column 0 of the tree's model
treeViewCol.add_attribute(colCellText, "text", 0)
# Bind the image cell to column 1 of the tree's model
treeViewCol.add_attribute(colCellImg, "pixbuf", 1)
# Append the columns to the TreeView
fileSystemTreeView.append_column(treeViewCol)
# add "on expand" callback
fileSystemTreeView.connect("row-expanded", onRowExpanded)
# add "on collapse" callback
fileSystemTreeView.connect("row-collapsed", onRowCollapsed)
scrollView = Gtk.ScrolledWindow()
scrollView.add(fileSystemTreeView)

# append the scrollView to the window (this)
window.add(scrollView)

window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()

答案 1 :(得分:0)

您所需要的通常称为lazy loading which is currently not supported by/on the ideas page of GtkTreeStore,但您仍然可以创建自己的YourTreeStoreLazy来实现GtkTreeModel界面。这在过去已经完成了几次,但我似乎无法找到任何合理的代码示例。有关如何实现getter实现的一些想法,请查看this post and its comments(link gone) wayback archive copy