python - 在 QListFiew 中过滤/搜索 QFileSystemModel(可能是 QSortFilterProxyModel)

标签 python python-3.x pyqt pyqt5

我想做的是过滤/搜索使用 QFileSystemModel 来填充它的 QListView:这是我现在使用我制作的测试/虚拟文件夹的一些窗口

(我正在制作一个批量文件“重命名器”,这只是我决定边学习边做的项目)

我希望能够通过在“getOut”行编辑中输入内容来搜索/过滤 ListView 。像这样的事情是我的目标(来自旧的随机 YouTube 视频但它使用 QListWidget

我读到 QSortFilterProxyModel 可能是我想要使用的,但是当我使用代理设置 ListView “setRootIndex”时 - 它会抛出错误。

TypeError:index(self,int,int,parent:QModelIndex = QModelIndex()):参数1具有意外的类型“str”

所以我的问题归结为:

  1. 是否有可能像我在上面的 gif 中想要的那样过滤 QListView?
  2. QFileSystemModel 可以这样过滤/搜索吗?
  3. 如果上述两个都可以的话,QSortFilterProxyModel 是否是适合该工作的工具?
  4. 我应该使用不同的模型还是制作一个(我认为可以)更基本且易于过滤的模型?

我可以通过仅使用 QFileSystemModel 的“setNameFilters”和“setNameFilterDisables(False)”来完成我想要做的事情,但我必须以一种奇怪的方式来做,你可以在下面看到。

def listPopulate(self):
    print('\ninside the listPopulate method now')
    getOut = self.getOutInputBox.text()
    gList = []
    gList.insert(0, getOut)
    if self.homes:
        if os.path.exists(self.homes):
            listModel = QtWidgets.QFileSystemModel()
            listModel.setFilter(QDir.NoDotAndDotDot | QDir.AllEntries | QDir.Dirs | QDir.Files)
            listModel.setRootPath(self.homes)

            # proxyModel = QtCore.QSortFilterProxyModel()
            # proxyModel.setSourceModel(listModel)

            self.mainListView.setModel(listModel)
            self.mainListView.setRootIndex(listModel.index(self.homes))
            if not getOut:
                print('\ngetOut empty')
            else:
                print(getOut)
                listModel.setNameFilters(gList)
                listModel.setNameFilterDisables(False)

_所有“gList”内容是因为“setNameFilters”仅接受列表(我假设这通常用于过滤文件扩展名),所以我采用 getOut Filter 并将其放入列表中。我可以让它按照我想要的方式进行过滤,但我必须输入“q”之类的内容才能过滤其中包含“Q”的内容。 “self.homes”只是用户选择的我的路径/目录。

最佳答案

如果使用 QSortFilterProxyModel 正确实现了 QFileSystemModel 过滤,那么您的所有问题都将得到解答。

以下解决方案仅适用于 Qt>=5.10,因为在该版本中我们添加了 recursiveFilteringEnabled 属性,该属性允许在树模型中进行递归过滤,如此例所示。

另一方面,当您想使用 QSortFilterProxyModel 时,您表明您遇到了问题,在指出问题是什么之前,您必须明白,如果您知道模型是代理或模型,则 View 不知道并且不会引起您的兴趣。不,只需等待一个模型和属于该模型的 QModelIndex 作为 rootIndex。在您的情况下,您必须使用 mapFromSource() 方法将 QFileSystemModel 的索引转换为 QSortFilterProxyModel 的索引。

最后似乎存在一个错误,因为当数据被过滤并且变空时,rootIndex 在内部发生更改,因此必须像我在答案中所做的那样重新建立它。

from PyQt5 import QtCore, QtGui, QtWidgets

class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        le = QtWidgets.QLineEdit(textChanged=self.on_textChanged)
        self.lv = QtWidgets.QListView()

        self._dirpath = QtCore.QDir.homePath()

        self.file_model = QtWidgets.QFileSystemModel()
        self.file_model.setRootPath(QtCore.QDir.rootPath())
        self.file_model.setFilter(QtCore.QDir.NoDotAndDotDot 
            | QtCore.QDir.AllEntries 
            | QtCore.QDir.Dirs 
            | QtCore.QDir.Files)
        self.proxy_model = QtCore.QSortFilterProxyModel(
            recursiveFilteringEnabled=True,
            filterRole=QtWidgets.QFileSystemModel.FileNameRole)
        self.proxy_model.setSourceModel(self.file_model)
        self.lv.setModel(self.proxy_model)
        self.adjust_root_index()

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(le)
        lay.addWidget(self.lv)

    @QtCore.pyqtSlot(str)
    def on_textChanged(self, text):
        self.proxy_model.setFilterWildcard("*{}*".format(text))
        self.adjust_root_index()

    def adjust_root_index(self):
        root_index = self.file_model.index(self._dirpath)
        proxy_index = self.proxy_model.mapFromSource(root_index)
        self.lv.setRootIndex(proxy_index)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

关于python - 在 QListFiew 中过滤/搜索 QFileSystemModel(可能是 QSortFilterProxyModel),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53772564/

相关文章:

python - SQLAlchemy - 属性错误 : _reverse_property

python - 尝试通过二分搜索找到非完美立方体的立方根时出现无限循环

c++ - Qt QString::split() 的相反方法

python - 如何知道QTableWidget的单元格是否正在被编辑?

python - 使用已弃用的 Numpy API

Python - 如何插入 NULL mysql 值

python - 如何使用正则表达式用空格替换字符之间的破折号

python - 如何在 Pandas 中创建日期时间索引

python - 从 qml 获取委托(delegate)对象名称到 python

python - 使用 python suds 从 Web 服务响应时出现 Unicode 错误