猿问

filterAcceptsRow() 究竟做了什么?

一个目录中有3个文件夹:


f:/root_folder/folder1

f:/root_folder/_folder2

f:/root_folder/folder3.asset

我尝试自定义 QSortFilterProxyModel.filterAcceptsRow() 仅显示带有 .asset 后缀的文件夹。


** 我知道我可以使用 QFileSystemModel.setNameFilters([*.asset]) 来做到这一点。但有时它不起作用。


我有 Python3.7 + PySide2 5.13.0。


# first inherit a QFileSystemModel instance:

listModel = QFileSystemModel()


# let the instance display only folders, except for '.' and '..':

listModel.setFilter(QDir.NoDotAndDotDot | QDir.Dirs)


# assgin a root path. i just want the model to search the 'f:/root_folder':

listModel.setRootPath("f:/root_folder")


# add a custom QSortFilterProxyModel:

myProxy = myProxyModel()

myProxy.setSourceModel(listModel)


# finally show result in a QListView:

# 'ui' is a QWidget object that contain a listView widget.

ui.listView.setModel(myProxy)

ui.listView.setRootIndex(myProxy.mapFromSource(listModel.index("f:/root_folder")))

这是自定义的 QSortFilterProxyModel:


# test:

class myProxyModel(QSortFilterProxyModel):

    def filterAcceptsRow(self, source_row, source_parent):

        return True

此时,脚本按预期工作:列表中有 3 个文件夹且没有过滤器。


如果我理解正确,“source_parent”应该是“listModel”的 QModelIndex,它指向目录“f:/root_folder”。并且“source_row”应该是“f:/root_folder”(三个文件夹之一)中某个项目的“序号”。对?


然后我添加了自己的过滤器:


# first try:

class myProxyModel(QSortFilterProxyModel):

    def filterAcceptsRow(self, source_row, source_parent):

        source_model = self.sourceModel() 

        # 'source_model' should be the 'listModel', right?


        source_index = source_model.index(source_row, 0, source_parent)

        # 'source_index' is a QModelIndex, pointing to 'folder1' or '_folder2' or 'folder3.asset'.


        # start filtering

        filename = source_index.data(Qt.DisplayRole)

        print(filename) # check

        if filename[-6:] == ".asset": return True

        else: return False

它应该在控制台上显示 3 个文件夹名称,在列表中显示 1 个文件夹(folder3.asset)。但我得到了非常奇怪的结果!这是控制台的结果:**它多次列出了我所有的硬盘


HDD (F:)

root_folder

HDD (F:)

HDD (E:)

HDD (D:)

C:

HDD (F:)

HDD (E:)

HDD (D:)

C:

现在我完全糊涂了。

filterAcceptsRow() 到底是做什么的?


慕森卡
浏览 284回答 2
2回答

胡说叔叔

您只需过滤与 QFileSystemModel 的 rootPath() 关联的 inde 的子项:from PySide2 import QtCore, QtGui, QtWidgetsclass SuffixDirProxyModel(QtCore.QSortFilterProxyModel):    def __init__(self, parent=None):        super().__init__(parent)        self._suffix = ""    def filterAcceptsRow(self, source_row, source_parent):        source_model = self.sourceModel()        if (            self._suffix            and isinstance(source_model, QtWidgets.QFileSystemModel)            and source_parent == source_model.index(source_model.rootPath())        ):            index = source_model.index(source_row, 0, source_parent)            name = index.data(QtWidgets.QFileSystemModel.FileNameRole)            file_info = source_model.fileInfo(index)            return name.split(".")[-1] == self._suffix and file_info.isDir()        return True    @property    def suffix(self):        return self._suffix    @suffix.setter    def suffix(self, s):        self._suffix = s        self.invalidateFilter()if __name__ == "__main__":    import sys    app = QtWidgets.QApplication(sys.argv)    model = QtWidgets.QFileSystemModel()    model.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Dirs)    path = # "f:/root_folder"    model.setRootPath(path)    proxy = SuffixDirProxyModel()    proxy.suffix = "asset"    proxy.setSourceModel(model)    w = QtWidgets.QListView()    w.setViewMode(QtWidgets.QListView.IconMode)    w.setModel(proxy)    w.setRootIndex(proxy.mapFromSource(model.index(path)))    w.show()    sys.exit(app.exec_())

喵喔喔

如果你不超载它什么都没有。QSortFilterProxyModel如果您使用的类中提供的过滤器通常不能满足您的需求,您只需要重载它。
随时随地看视频慕课网APP

相关分类

Python
我要回答