[英]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”(三個文件夾之一)中某個項目的“序號”。 對?
然后我添加了我自己的過濾器:
# 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() 關聯的 inde 的子代:
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_())
如果你不超載它什么都沒有。
如果您使用的類中提供的過濾器(通常為QSortFilterProxyModel
)不能滿足您的需要,您只需重載它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.