我按照 python-gtk-3-tutorial 并使用 Gtk TreeView 实现了一个简单的文件浏览器。它运行得很好,但我的问题是,在初始化时 TreeView 中的第一个项目已被默认选中。
我使用以下命令初始化 TreeSelection:
treeSelection = treeView.get_selection()
然后我将树选择与回调函数连接起来:
treeSelection.connect("changed", treeSelectionChanged)
def treeSelectionChanged(treeSelection):
treeModel, treeIter = treeSelection.get_selected()
if treeIter != None:
print "You selected", treeModel[treeIter][0]
当我的应用程序启动时,TreeView 中的第一个条目已被选中,并且其名称被打印出来。如果我重新读取数据并清除树模型(treeStore.clear()) 我还收到了对 TreeView 中“更改”的响应,并且 TreeView 中其他项目的名称也被打印出来。
我不知道如何在清除 TreeStore 之前取消选择默认选择并取消选择所有项目。我不知道该怎么做。有人能指出我的错误吗?以下是示例代码:
#!/usr/bin/python
import os, stat
from gi.repository import Gtk
from gi.repository.GdkPixbuf import Pixbuf
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Simple Photo Importer", default_width = 400,default_height = 600)
# initialize new Gtk box container
self.fileSystemTreeBox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 5)
self.add(self.fileSystemTreeBox)
# initialize the filesystem treestore
self.fileSystemTreeStore = Gtk.TreeStore(str, Pixbuf, str, bool)
# populate the tree store
self.populateFileSystemTreeStore(self.fileSystemTreeStore, '/home/karlitos')
# initialize the TreeView
self.fileSystemTreeView = Gtk.TreeView(self.fileSystemTreeStore)#, default_width = 400,default_height = 600)
self.fileSystemTreeView.set_headers_visible(False)
#self.fileSystemTreeView.columns_autosize()
# Create a TreeViewColumn
treeViewCol = Gtk.TreeViewColumn(title=None)
treeViewCol.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
#treeViewCol.expand = True
# 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
self.fileSystemTreeView.append_column(treeViewCol)
# add "on expand" callback
self.fileSystemTreeView.connect("row-expanded", self.onRowExpanded)
# add "on collapse" callback
self.fileSystemTreeView.connect("row-collapsed", self.onRowCollapsed)
# add tree view selection
fileSystemTreeSelection = self.fileSystemTreeView.get_selection()
fileSystemTreeSelection.connect("changed", self.fileSystemTreeSelectionChanged)
# add scroll view
self.scrollView = Gtk.ScrolledWindow()
self.scrollView.add(self.fileSystemTreeView)
# append the scrollView to the window (this)
#self.add(self.scrollView)
self.fileSystemTreeBox.pack_start(self.scrollView, True, True, 0)
# add a button for selecting different folder
self.readNewDirButton = Gtk.Button(label="Read new directory")
self.readNewDirButton.connect("clicked", self.readNewDirectory)
#self.add(self.readNewDirButton)
self.fileSystemTreeBox.pack_start(self.readNewDirButton, False, False, 0)
def populateFileSystemTreeStore(self, treeStore, path, parent=None):
appendHiddenItems = False
folders = []
files = []
# iterate over the items in the path
for item in os.listdir(path):
# skip item if it's name brgiins with '.' and appendHiddenItems ist set to 'false'
if not appendHiddenItems and item[0] == '.': continue
# 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 with corresponding metadata to related arrays
if itemIsFolder:
folders.append([item, itemIcon, itemFullname, itemIsFolder])
else:
files.append([item, itemIcon, itemFullname, itemIsFolder])
# append dummy when no entries in the current folder
if not folders and not files: treeStore.append(parent, [None, None, None, None])
else:
for folderEntry in sorted(folders):
# append the folders
currentIter = treeStore.append(parent, folderEntry)
# append the dummy nodes to the folders
treeStore.append(currentIter, [None, None, None, None])
for fileEntry in sorted(files):
treeStore.append(parent, fileEntry)
def onRowExpanded(self, 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
self.populateFileSystemTreeStore(treeStore, newPath, treeIter)
# remove the first child (dummy node)
treeStore.remove(treeStore.iter_children(treeIter))
def onRowCollapsed(self, 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, None])
def readNewDirectory(self, widget):
# initialize the open directory dialog
openDirectoryDialog = Gtk.FileChooserDialog("Please choose a folder", self,
Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL,
Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK))
openDirectoryDialog.set_default_size(800, 400)
# initialize the response
openDirectoryResponse = openDirectoryDialog.run()
if openDirectoryResponse == Gtk.ResponseType.OK:
self.fileSystemTreeStore.clear()
self.populateFileSystemTreeStore(self.fileSystemTreeStore, openDirectoryDialog.get_filename())
#elif openDirectoryResponse == Gtk.ResponseType.CANCEL:
#do something
openDirectoryDialog.destroy()
def fileSystemTreeSelectionChanged(self, fileSystemTreeSelection):
fileSystemTreeModel, fileSystemTreeIter = fileSystemTreeSelection.get_selected()#_rows()
if fileSystemTreeIter != None:
print "You selected", fileSystemTreeModel[fileSystemTreeIter][0]
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
答案1
有一个函数可以完全按照您的要求执行操作,但在您的示例中不起作用__init__
,这个函数称为unselect_all
,属于 Gtk.TreeSelection。所以我拿 riverbed 来编辑他的例子。
原谅英语,摘自谷歌翻译。
#!/usr/bin/python
import os, stat
from gi.repository import Gtk
from gi.repository.GdkPixbuf import Pixbuf
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Simple Photo Importer", default_width = 400,default_height = 600)
# initialize new Gtk box container
self.firstSelection = True
self.fileSystemTreeBox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 5)
self.add(self.fileSystemTreeBox)
# initialize the filesystem treestore
self.fileSystemTreeStore = Gtk.TreeStore(str, Pixbuf, str, bool)
# populate the tree store
self.populateFileSystemTreeStore(self.fileSystemTreeStore, os.path.expanduser('~'))
# initialize the TreeView
self.fileSystemTreeView = Gtk.TreeView(self.fileSystemTreeStore)#, default_width = 400,default_height = 600)
self.fileSystemTreeView.set_headers_visible(False)
#self.fileSystemTreeView.columns_autosize()
# Create a TreeViewColumn
treeViewCol = Gtk.TreeViewColumn(title=None)
treeViewCol.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
#treeViewCol.expand = True
# 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
self.fileSystemTreeView.append_column(treeViewCol)
# add "on expand" callback
self.fileSystemTreeView.connect("row-expanded", self.onRowExpanded)
# add "on collapse" callback
self.fileSystemTreeView.connect("row-collapsed", self.onRowCollapsed)
# add tree view selection
fileSystemTreeSelection = self.fileSystemTreeView.get_selection()
fileSystemTreeSelection.connect("changed", self.fileSystemTreeSelectionChanged)
# add scroll view
self.scrollView = Gtk.ScrolledWindow()
self.scrollView.add(self.fileSystemTreeView)
# append the scrollView to the window (this)
#self.add(self.scrollView)
self.fileSystemTreeBox.pack_start(self.scrollView, True, True, 0)
# add a button for selecting different folder
self.readNewDirButton = Gtk.Button(label="Read new directory")
self.readNewDirButton.connect("clicked", self.readNewDirectory)
#self.add(self.readNewDirButton)
self.fileSystemTreeBox.pack_start(self.readNewDirButton, False, False, 0)
def populateFileSystemTreeStore(self, treeStore, path, parent=None):
appendHiddenItems = False
folders = []
files = []
# iterate over the items in the path
for item in os.listdir(path):
# skip item if it's name brgiins with '.' and appendHiddenItems ist set to 'false'
if not appendHiddenItems and item[0] == '.': continue
# 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 with corresponding metadata to related arrays
if itemIsFolder:
folders.append([item, itemIcon, itemFullname, itemIsFolder])
else:
files.append([item, itemIcon, itemFullname, itemIsFolder])
# append dummy when no entries in the current folder
if not folders and not files: treeStore.append(parent, [None, None, None, None])
else:
for folderEntry in sorted(folders):
# append the folders
currentIter = treeStore.append(parent, folderEntry)
# append the dummy nodes to the folders
treeStore.append(currentIter, [None, None, None, None])
for fileEntry in sorted(files):
treeStore.append(parent, fileEntry)
def onRowExpanded(self, 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
self.populateFileSystemTreeStore(treeStore, newPath, treeIter)
# remove the first child (dummy node)
treeStore.remove(treeStore.iter_children(treeIter))
def onRowCollapsed(self, 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, None])
def readNewDirectory(self, widget):
# initialize the open directory dialog
openDirectoryDialog = Gtk.FileChooserDialog("Please choose a folder", self,
Gtk.FileChooserAction.SELECT_FOLDER, (Gtk.STOCK_CANCEL,
Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK))
openDirectoryDialog.set_default_size(800, 400)
# initialize the response
openDirectoryResponse = openDirectoryDialog.run()
if openDirectoryResponse == Gtk.ResponseType.OK:
self.fileSystemTreeStore.clear()
self.populateFileSystemTreeStore(self.fileSystemTreeStore, openDirectoryDialog.get_filename())
#elif openDirectoryResponse == Gtk.ResponseType.CANCEL:
#do something
openDirectoryDialog.destroy()
def fileSystemTreeSelectionChanged(self, fileSystemTreeSelection):
fileSystemTreeModel, fileSystemTreeIter = fileSystemTreeSelection.get_selected()#_rows()
if fileSystemTreeIter != None and not self.firstSelection:
print "You selected", fileSystemTreeModel[fileSystemTreeIter][0]
elif self.firstSelection:
fileSystemTreeSelection.unselect_all()
self.firstSelection = False
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()