代码之家  ›  专栏  ›  技术社区  ›  wayfarer

使用QtCore进行QListView搜索。QSortFilterProxyModel在某些情况下不起作用

  •  0
  • wayfarer  · 技术社区  · 2 年前

    我找到了这个代码 here 在论坛中,只是为PySide2更改了它,但有时它不起作用,我在自己的工具中实现了这个搜索,在那里也是一样的,在一些条目中,当它不存在时,以第一个字母或数字显示listview重置为根文件夹“”:(

    from PySide2 import QtCore, QtGui, QtWidgets
    
    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
            le = QtWidgets.QLineEdit()
            le.textChanged.connect(self.on_textChanged)
            self.lv = QtWidgets.QListView()
    
            self._dirpath = "d:/"
    
            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.Slot(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_())
    

    enter image description here

    0 回复  |  直到 2 年前
        1
  •  0
  •   musicamante    2 年前

    这个问题是由递归搜索本身引起的。

    这种搜索确保 任何 在其子树中至少有一个匹配项的顶级项。

    现在,虽然这种方法通常适用于树视图中显示的标准搜索,但在处理将非 模型

    在您的情况下,您可以看到C:驱动器,因为搜索算法在 整体 文件系统,特别是在C:驱动器中。

    同时,您正试图基于D:设置根索引,但该搜索在该树节点内不返回任何结果,而且由于返回的索引实际上是无效的,因此它将重置根索引:请记住,无效的QModelIndex总是指模型的根。因为,在这一点上,过滤器显示 某物 在C中:匹配搜索,这就是您可以看到的。

    如果你有另一个驱动器,其中有一个包含“x”的文件或文件夹,你可能也会看到那个驱动器。

    QSortFilterProxyModel不允许设置递归筛选器的“深度”,并且还需要搜索筛选器才能显示视图的根索引(这不是顶级项)。

    我能建议的唯一解决方案是始终检查映射索引的有效性:如果它有效,则继续 setRootIndex() ,否则将完全禁用递归功能。

    然后,每当搜索发生更改时,您都需要再次恢复它。

        def on_textChanged(self, text):
            self.proxy_model.setFilterWildcard("*{}*".format(text))
            self.proxy_model.setRecursiveFilteringEnabled(True)
            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)
            if not proxy_index.isValid():
                self.proxy_model.setRecursiveFilteringEnabled(False)
            else:
                self.lv.setRootIndex(proxy_index)
    

    另一种可能性是不直接在视图中使用排序筛选器,而是创建一个独立的QStandardItemModel,并在代理更改其筛选器时始终通过迭代父级的映射源索引来重新填充它:如果父级有效,请尝试附加其子级。