python - 在 QListFiew 中过滤/搜索 QFileSystemModel(可能是 QSortFilterProxyModel)
问题描述
我想要做的是过滤/搜索使用 QFileSystemModel 填充它的 QListView:这是我现在使用我制作的测试/虚拟文件夹的一些窗口
(我正在制作一个批量文件“重命名器”,只是我决定学习的项目)
我希望能够通过在“getOut”行编辑中输入一些内容来搜索/过滤列表视图。像这样的东西是我的目标(它来自一个旧的随机 youtube 视频,但它使用的是 QListWidget
我读到 QSortFilterProxyModel 可能是我想要使用的,但是当我使用代理设置列表视图“setRootIndex”时 - 它会引发错误。
TypeError: index(self, int, int, parent: QModelIndex = QModelIndex()): argument 1 has unexpected type 'str'
所以我的问题归结为:
- 甚至可以像我在上面的 gif 中那样过滤 QListView 吗?
- QFileSystemModel 是否能够像那样被过滤/搜索?
- 如果上述 2 都可以,QSortFilterProxyModel 是否是适合该工作的工具?
- 我应该使用不同的模型还是制作一个(我认为你可以)更基本且对过滤开放的模型?
我可以通过只使用 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过滤器扔到一个列表中。我可以让它按我想要的方式过滤,但我必须输入“ q ”之类的东西才能过滤到里面有“Q”的东西。而“self.homes”只是用户选择的路径/目录。
解决方案
如果使用 QSortFilterProxyModel 正确实现了 QFileSystemModel 过滤,您的所有问题都会得到解答。
以下解决方案仅适用于 Qt>=5.10,因为在该版本中,我们添加了recursiveFilteringEnabled
允许在树模型中进行递归过滤的属性,如本例所示。
另一方面,您表示当您想使用 QSortFilterProxyModel 时遇到了问题,在指出问题是什么之前,您必须了解视图不知道并且您不感兴趣,如果您知道模型是否是代理,只需等待一个模型和一个 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 - Python海龟——如何画蜘蛛网
- php - 我的提交按钮不起作用,而是触发了 Ajax 请求
- postgresql - 使用 x509 证书登录 PostgreSQL
- drupal - 添加菜单链接 Drupal 8
- heroku - 在 Heroku 中使用自定义域部署 Web 应用程序所需的东西
- vectorization - icc的向量化和ispc的向量化有什么区别?
- javascript - 替代导入全局 es6 常量
- python - 如何在不将所有内容都放在 try/except 块中的情况下处理可能丢失的包?
- ios - 登录后查看脱臼或取消firebase社交登录swift
- couchbase - 如何在 n1ql Couchbase 中创建具有所有组合的对数组