【问题标题】:How to use the indices of a QFileSystemModel to track a subset of items?如何使用 QFileSystemModel 的索引来跟踪项目的子集?
【发布时间】:2017-12-03 20:40:50
【问题描述】:

我正在尝试创建一个文件选择器对话框,该对话框使用复选框来允许选择多个文件。此外,我想对话以从已经选择的一些项目开始。我在网上找到了一些使用QTreeViewQFileSystemModel 的子类来执行此操作的示例。对话框完全呈现后,如何将最初检查的文件路径列表与模型中描述这些路径的 QModelIndex 项目联系起来?

我查看的示例保留了应检查哪些QModelIndex 项目的列表,并覆盖了QFileSystemModel 子类的某些方法,例如data() 方法以在选中或取消选中项目时更新此列表。为了支持在首次创建对话框时检查某些项目,我尝试使用应预先检查的第二个文件路径列表。在我的QFileSystemModel 子类的data() 方法中,我检查QModelIndex 输入的文件路径,如果它在我的预检查列表中,我从预检查列表中删除文件路径并放入QModelIndex 进入另一个检查项目列表。我遇到的问题是该模型似乎在创建过程中多次自我再生。第一次为具有特定路径的索引调用 data() 时,从预检查列表中删除该路径,并将 QModelIndex 添加到另一个列表中。但是,一旦对话框完全显示,该文件路径的 QModelIndex 与放入预检查列表中的实例不同,因此我的代码不知道应该检查它。

这里有一个例子来说明我的意思:

import os
import sys

from PyQt5 import QtWidgets

all_entries = list()


class MyFileSystemModel(QtWidgets.QFileSystemModel):

    def data(self, index, role):
        if index not in all_entries:
            all_entries.append(index)
        return super().data(index, role)


class Ui_Dialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        QtWidgets.QDialog.__init__(self, parent)

        self.model = MyFileSystemModel()
        self.model.setRootPath(os.path.abspath('.'))

        self.tree = QtWidgets.QTreeView()
        self.tree.setModel(self.model)
        self.tree.setRootIndex(self.model.index(os.path.abspath('.')))

        self.llayout = QtWidgets.QVBoxLayout(parent)
        self.but = QtWidgets.QPushButton("OK")

        self.llayout.addWidget(self.tree)
        self.llayout.addWidget(self.but)

        self.setLayout(self.llayout)

        self.but.clicked.connect(self.print_entries)

    def print_entries(self):
        print('*'*80)
        for index in all_entries:
            print(index, os.path.relpath(self.model.filePath(index),
                                         os.path.abspath('.')))


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_Dialog()
    ui.show()

    sys.exit(app.exec_())

在包含一个名为 test 的单个文件的目录中运行此脚本,然后单击 OK 按钮,我明白了

********************************************************************************
<PyQt5.QtCore.QModelIndex object at 0x7ff46b991f28> test
<PyQt5.QtCore.QModelIndex object at 0x7ff46b991f98> test
<PyQt5.QtCore.QModelIndex object at 0x7ff46b910048> test
<PyQt5.QtCore.QModelIndex object at 0x7ff46b9100b8> test

所以all_entriestest 文件路径的四个不同QModelIndex 项目结束。在我更多涉及的可检查对话框中,我最终会在已检查项目列表中使用0x7ff46b991f28QModelIndex 实例,但似乎一旦显示对话框,我就需要使用0x7ff46b9100b8 的实例。我可以处理我自己的路径列表中的所有内容而不使用 QModelIndex 对象,但使用它们的好处是 QFileSystemModel 使用文件系统观察程序来跟踪文件系统更改,我想利用它跟踪所选文件的属性,而无需查询文件系统来判断文件是否已更改。

【问题讨论】:

    标签: python qt pyqt


    【解决方案1】:

    问题有以下原因:

    • QModelIndex 不应用于区分模型的项目,根据docs

    注意:模型索引应立即使用,然后丢弃。你 调用模型后不应依赖索引保持有效 更改模型结构或删除项目的功能。如果 随着时间的推移,您需要使用 QPersistentModelIndex 保持模型索引。

    • 一个文件在QFileSystemModel中有几个关联的列,保存第一列的索引比较合适。

    考虑到这两件事,代码应该如下:

    all_entries = list()
    
    
    class MyFileSystemModel(QtWidgets.QFileSystemModel):
        def data(self, index, role):
            if index.column() == 0:
                if QPersistentModelIndex(index) not in all_entries:
                    all_entries.append(QPersistentModelIndex(index))
            return super().data(index, role)
    
    [...]
    
    def print_entries(self):
        print('*'*80)
        for index in all_entries:
            ix = QModelIndex(index) # get QModelIndex from QPersistentModelIndex
            print(index, os.path.relpath(self.model.filePath(ix),os.path.abspath('.')))
    

    【讨论】:

      猜你喜欢
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-29
      • 1970-01-01
      相关资源
      最近更新 更多