web-dev-qa-db-fra.com

Désélectionnez le Gtk TreeSelection lors de la clera du modèle TreeStore

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()
2
karlitos

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()
1
user2461236