我正在尝试使用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
答案 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。