filterAcceptsRow() 究竟做了什么?
What does filterAcceptsRow() exactly do?
一个目录下有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' 中项目的 "ordinal number",三个文件夹之一。对吗?
然后我添加了自己的过滤器:
# 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:
并且 listView 是空的。
'source_parent'无效吗?然后我试试这个:
class myProxyModel(QSortFilterProxyModel):
def filterAcceptsRow(self, source_row, source_parent):
if not source_parent.isValid():
print("index invalid")
return False
else: return True
在控制台上得到这个:
index invalid
index invalid
和 listView 中的 3 个文件夹:
现在我完全糊涂了。
filterAcceptsRow() 到底做了什么?
您只需要过滤与 QFileSystemModel 的 rootPath() 关联的索引的子项:
from PySide2 import QtCore, QtGui, QtWidgets
class 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_())
如果你不超载就什么都没有。
只有当您使用的 class 中提供的过滤器(通常 QSortFilterProxyModel
)不能满足您的需求时,您才需要重载它。
一个目录下有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' 中项目的 "ordinal number",三个文件夹之一。对吗?
然后我添加了自己的过滤器:
# 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:
并且 listView 是空的。
'source_parent'无效吗?然后我试试这个:
class myProxyModel(QSortFilterProxyModel):
def filterAcceptsRow(self, source_row, source_parent):
if not source_parent.isValid():
print("index invalid")
return False
else: return True
在控制台上得到这个:
index invalid
index invalid
和 listView 中的 3 个文件夹:
现在我完全糊涂了。
filterAcceptsRow() 到底做了什么?
您只需要过滤与 QFileSystemModel 的 rootPath() 关联的索引的子项:
from PySide2 import QtCore, QtGui, QtWidgets
class 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_())
如果你不超载就什么都没有。
只有当您使用的 class 中提供的过滤器(通常 QSortFilterProxyModel
)不能满足您的需求时,您才需要重载它。