J'ai suivi le tutoriel python-gtk-3 et implémenté un simple navigateur de fichiers à l'aide de Gtk TreeView. Cela fonctionne plutôt bien, mais mon problème est que, au moment de l'initialisation, le premier élément du TreeView est déjà sélectionné par défaut.
J'initialise TreeSelection en utilisant:
treeSelection = treeView.get_selection()
Ensuite, je connecte la sélection d'arborescence avec une fonction de rappel:
treeSelection.connect("changed", treeSelectionChanged)
def treeSelectionChanged(treeSelection):
treeModel, treeIter = treeSelection.get_selected()
if treeIter != None:
print "You selected", treeModel[treeIter][0]
Lorsque mon application démarre, la première entrée dans TreeView est déjà sélectionnée et son nom est imprimé. Si je relis les données et efface le modèle d'arbre (treeStore.clear ()) j'obtiens également des réponses aux "changements" dans TreeView et les noms des autres éléments dans TreeView sont également imprimés en dehors.
Je ne sais pas comment désélectionner la sélection effectuée par défaut et désélectionner tous les éléments avant d'effacer le TreeStore. Je ne pouvais pas comprendre comment. Quelqu'un pourrait-il me signaler mon erreur? Voici l'exemple de code:
#!/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()
Il existe une fonction qui fait exactement ce que vous demandez, mais qui ne fonctionnerait pas dans le __init__
de votre exemple, cette fonction s'appelle unselect_all
, et appartient à Gtk.TreeSelection. J'ai donc pris le lit de la rivière pour éditer son exemple.
Pardonnez l'anglais, est extrait du traducteur Google.
#!/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()