4

我正在尝试模型/视图编程中的示例。

http://doc.qt.io/qt-5/model-view-programming.html

为了演示如何使用模型索引从模型中检索数据,我们设置了一个没有视图的 QFileSystemModel,并在小部件中显示文件和目录的名称。虽然这并没有展示使用模型的正常方式,但它展示了模型在处理模型索引时使用的约定。

我们通过以下方式构建文件系统模型:

QFileSystemModel *model = new QFileSystemModel;
QModelIndex parentIndex = model->index(QDir::currentPath());
int numRows = model->rowCount(parentIndex);

在这种情况下,我们设置了一个默认的 QFileSystemModel,使用该模型提供的 index() 的特定实现获取父索引,并使用 rowCount() 函数计算模型中的行数。

这是我的代码:

QFileSystemModel* model = new QFileSystemModel;
QModelIndex parentIndex = model->index(QDir::currentPath());
qDebug() << QDir::currentPath();
// "/media/Local Data/Files/Programming/C++/build-DemostrateQModelIndex-Desktop_Qt_5_5_1_GCC_64bit-Debug"
qDebug() << "RowCount is " << model->rowCount(parentIndex);

但 RowCount 始终为 0。

在“build-DemostrateQModelIndex-Desktop_Qt_5_5_1_GCC_64bit-Debug”文件夹中,里面有文件和文件夹。我希望行数应该是里面的项目数。

我也尝试过初始化 QFileSystemModel;

QFileSystemModel* model = new QFileSystemModel;
model->setRootPath(QDir::rootPath());
QModelIndex parentIndex = model->index(QDir::currentPath());
qDebug() << "RowCount is " << model->rowCount(parentIndex);

RowCount 仍为 0。

更新 1:应用 Johannes Schaub 的建议。QEventLoop我在我的代码中添加了一个。

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QFileSystemModel* model = new QFileSystemModel;
    model->setRootPath(QDir::rootPath());
    QModelIndex parentIndex = model->index(QDir::currentPath());
    qDebug() << QDir::currentPath();
    // "/media/Local Data/Files/Programming/C++/build-DemostrateQModelIndex-Desktop_Qt_5_5_1_GCC_64bit-Debug"
    qDebug() << "First RowCount Call is " << model->rowCount(parentIndex);

    QEventLoop loop;
    QObject::connect(model, &QFileSystemModel::directoryLoaded, &loop, &QEventLoop::quit);
    loop.exec();
    qDebug() << "RowCount Call after eventloop is  " << model->rowCount(parentIndex);

    return a.exec();
}

我的行数仍然为 0。

4

2 回答 2

3

QFileSystemModel 利用延迟加载和延迟加载。您需要注意它的信号,这些信号将不断发出,直到整个目录被加载。

特别是,文档说

与 QDirModel 不同,QFileSystemModel 使用单独的线程来填充自身,因此不会导致主线程在查询文件系统时挂起。在模型填充目录之前,对 rowCount() 的调用将返回 0。

在您的情况下,您可能可以运行本地 QEventLoop 并将模型的各个信号(directoryLoaded)与事件循环的 quit() 插槽连接以等待填充。我不确定 canFetchMore 和 fetchMore 是否可以用于这种情况以及阻止等待人口(afaik 它的主要用途是当用户在无限列表中向下滚动时延迟加载,例如 facebook pinwall 流)。至少值得一试。

@Kuba 正确地指出,本地事件循环本质上不是必需的。如果您负担得起离开创建的上下文QFileSystemModel(例如,通过将其存储为指针成员),并将插槽作为普通成员函数进行操作。

于 2015-11-05T12:40:14.693 回答
0

使用原则是:

  • 创建模型并设置其根路径。在这个阶段,您可以假设模型仍然是空的或加载的数据很少。
  • 让模型在其单独的内部线程中加载数据。将信号连接directoryLoaded到插槽。当模型将加载根路径时,将发送信号。
  • 在插槽中,检查您感兴趣的文件夹是否已完全加载。一开始不会。原因是模型使用惰性方法加载,并且可能只有根路径文件夹准备就绪。
  • 如果您的文件夹尚未完全准备好,请让模型加载它。这是通过使用model.canFetchMoremodel.fetchMore感兴趣文件夹的索引并立即返回来完成的(或者您可以尝试使用已经准备好的文件夹条目,但这种替代方法需要管理模型准备就绪的进度)。
  • 当插槽准备就绪时(可能在调用 之后model.fetchMore,测试canFetchMore将返回False,这意味着您感兴趣的文件夹已完全加载,model.rowCount现在将返回正确的值。如果您对另一个文件夹感兴趣,请再次使用model.canFetchMoremodel.fetchMore索引的新文件夹。

除了使用model.canFetchMore,您还可以将感兴趣的文件夹的路径与传递给插槽的参数进行比较。此字符串指示发送信号的路径。


您表示您使用的是 C++,我没有这种语言的代码,但是 Python 中的以下代码可以很容易地翻译(self= this,缩进的行相当于分隔块的一对括号)


class MyWidget(QPlainTextEdit):

    def __init__(self):

        # Init superclass
        super(MyWidget, self).__init__()
        self.setReadOnly(True)
        self.show()

        # FS model, set root path
        self.model = QFileSystemModel()
        path = "C:/"
        self.model.setRootPath(path)

        # Perform next tasks after model root path is loaded
        self.model.directoryLoaded.connect(self.on_loaded)

    def on_loaded(self, loaded_path):
        # Folder to list
        folder_path = "C:/Users"  # <--- we are interested in this folder,
                                  #      not the root folder
        folder_index = self.model.index(folder_path)

        # Check the folder we are interested in is completely loaded
        if self.model.canFetchMore(folder_index):
            self.model.fetchMore(folder_index)
            return

        # Folder is now loaded, list children
        num_rows = self.model.rowCount(folder_index)
        for row in range(num_rows):
            # Child data
            num_columns = self.model.columnCount(folder_index)
            if num_columns > 0:
                # Child name in first column
                index = self.model.index(row, 0, folder_index)
                text += index.data(Qt.DisplayRole)

                # etc
于 2019-02-26T10:44:35.577 回答