Отмените выбор Gtk TreeSelection при очистке модели TreeStore [закрыто]

я следовал руководству python-gtk-3 и реализовал простой файловый браузер с использованием 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()
2
задан 5 July 2018 в 19:05

1 ответ

Существует функция, которая делает точно, что Вы спрашиваете, но не работали бы в __init__ из Вашего примера, эта функция вызвана unselect_all и принадлежит Gtk. TreeSelection. Таким образом, я взял русло для редактирования его примера.

Прощают английскому языку, извлечен из переводчика 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
ответ дан 2 December 2019 в 05:15

Другие вопросы по тегам:

Похожие вопросы: