Qt:使用 QListView 和 QFileSystemModel 浏览文件系统。如何突出显示文件夹中的第一项?

发布于 2024-11-28 20:12:47 字数 2987 浏览 2 评论 0原文

我正在没有键盘/鼠标的系统上执行该主题所说的操作,因此我需要“通过代码”来完成这项工作。当我更改 QListView 的 RootIndex 时,我想突出显示第一行。

这是我制作的一个小型测试项目中的 mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QEvent>
#include <QKeyEvent>
#include <QDebug>
#include <QTimer>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath("/Users/anders/Downloads/Browser");

    listView = new QListView;
    listView->setModel(model);
    listView->show();

    QTimer::singleShot(2000, this, SLOT(LightItUp1()));

}

void MainWindow::LightItUp1()
{
    qDebug("LightItUp1");
    listView->setRootIndex(model->index("/Users/anders/Downloads"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp2()));
}

void MainWindow::LightItUp2()
{
    qDebug("LightItUp2");
    listView->setRootIndex(model->index("/Users/anders/Downloads/Browser"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp3()));
}


void MainWindow::LightItUp3()
{
    qDebug("LightItUp3");
    listView->setRootIndex(model->index("/Users/anders/Downloads"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp4()));
}


void MainWindow::LightItUp4()
{
    QString p = "/Users/anders/Downloads/Mail";
    listView->setRootIndex(model->index(p));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));
}

MainWindow::~MainWindow()
{
    delete listView;
    delete model;
    delete ui;
}

在此示例中,LightItUp 1-3 执行了我想要的操作,但 LightItUp4 没有执行。如果我交换 2 和 2 中的文件夹4 他们都没有做到我想要的,而 1 和 1 都没有做到我想要的。 3 还在工作。我怀疑我误解了如何使用此模型/视图,但不知道是什么。

编辑:创建了一个更简单的示例,其中提到了@buck 的错误检查。请参阅源代码中的注释。

const QString rp = "/home/anders/src/";

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath(rp); //using model->setRootPath(rp + "/trunk") instead works

    listView = new QListView;
    listView->setModel(model);
    listView->show();

    QTimer::singleShot(2000, this, SLOT(LightItUp1()));

}

void MainWindow::LightItUp1()
{
    qDebug("LightItUp1");
    QModelIndex p = model->index(rp + "/trunk");
    if (!p.isValid()) {
        qDebug("index not valid\n");
        return;
    }

    //model->setRootPath(rp + "/trunk") here does not make it work
    listView->setRootIndex(p);
    listView->setCurrentIndex(model->index(0, 0, p));
}

我认为当我在模型上执行 setRootPath(rp) ,然后设置视图以使用模型时,如果我正确设置索引,视图应该能够在 rp 的所有子文件夹中移动。我将重读有关模型/视图、QListView 和 QFileSystemModel 的 Qtdocs,但想发布此内容以防有人理解发生了什么。

I'm doing what the topic says on a system without keyboard/mouse, so I need to make this work "from code". When I change the RootIndex of the QListView I want to highlight the first row.

Here's mainwindow.cpp from a small testproject I've made:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QEvent>
#include <QKeyEvent>
#include <QDebug>
#include <QTimer>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath("/Users/anders/Downloads/Browser");

    listView = new QListView;
    listView->setModel(model);
    listView->show();

    QTimer::singleShot(2000, this, SLOT(LightItUp1()));

}

void MainWindow::LightItUp1()
{
    qDebug("LightItUp1");
    listView->setRootIndex(model->index("/Users/anders/Downloads"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp2()));
}

void MainWindow::LightItUp2()
{
    qDebug("LightItUp2");
    listView->setRootIndex(model->index("/Users/anders/Downloads/Browser"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp3()));
}


void MainWindow::LightItUp3()
{
    qDebug("LightItUp3");
    listView->setRootIndex(model->index("/Users/anders/Downloads"));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));

    QTimer::singleShot(2000, this, SLOT(LightItUp4()));
}


void MainWindow::LightItUp4()
{
    QString p = "/Users/anders/Downloads/Mail";
    listView->setRootIndex(model->index(p));
    listView->setCurrentIndex(model->index(0, 0, listView->rootIndex()));
}

MainWindow::~MainWindow()
{
    delete listView;
    delete model;
    delete ui;
}

In this example LightItUp 1-3 do what I want, but LightItUp4 does not. If I swap the folders in 2 & 4 both of them fail to do what I want, while 1 & 3 still work. I suspect I have misunderstood something about how to use this Model/View, but have no idea what.

Edit: created a simpler example with the error checking @buck mentioned. See the comments in the source code.

const QString rp = "/home/anders/src/";

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath(rp); //using model->setRootPath(rp + "/trunk") instead works

    listView = new QListView;
    listView->setModel(model);
    listView->show();

    QTimer::singleShot(2000, this, SLOT(LightItUp1()));

}

void MainWindow::LightItUp1()
{
    qDebug("LightItUp1");
    QModelIndex p = model->index(rp + "/trunk");
    if (!p.isValid()) {
        qDebug("index not valid\n");
        return;
    }

    //model->setRootPath(rp + "/trunk") here does not make it work
    listView->setRootIndex(p);
    listView->setCurrentIndex(model->index(0, 0, p));
}

I thought that when I do setRootPath(rp) on the model, and then set the view to use the model, the view should able to move around in all subfolders of rp if I set the indexes correctly. I'll reread the Qtdocs on Model/View, QListView and QFileSystemModel, but wanted to post this in case someone understands what is happening.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一萌ing 2024-12-05 20:12:47

我从这里得到了一些帮助,这些是我的结论

:为了使 QFileSystemModel 正常工作,GUI 事件循环需要运行。我猜您因此添加了 QTimer::singleShot(...) 行?然而,你只给了它2秒钟。从 QFileSystemModel 的文档中:

调用 rowCount() 将返回 0,直到模型填充目录。

这意味着在构建 MainWindow 后,您有 2 秒的时间来构建其他所有内容、启动 GUI 事件循环,然后让 QFileSystemModel 填充目录。失败的目录是否很大?我猜是这样。

您可以尝试的是给计时器更长的间隔。更好的解决方案可能是创建一个快捷方式来选择列表中的第一个内容,如下所示:

QShortcut* sh = new QShortcut(QKeySequence("Ctrl+1"), this);
connect(sh, SIGNAL(activated()), this, SLOT(LightUpFirst()));

然后由 LightUpFirst 函数进行选择。希望有帮助!

I had some help from here and these are my conclusions:

In order for the QFileSystemModel to work properly, the GUI event loop needs to be running. I'm guessing you added the QTimer::singleShot(...) line because of this? However, you only gave it 2 seconds. From the documentation for QFileSystemModel:

Calls to rowCount() will return 0 until the model populates a directory.

This means after your MainWindow is constructed, you have 2 seconds for everything else to be constructed, the GUI event loop to start, and then for the QFileSystemModel to populate the directory. Are the directories where this is failing large? I am guessing so.

What you could try would be to give the timer a longer interval. A better solution may be to create a shortcut that selects the first thing in the list, like this:

QShortcut* sh = new QShortcut(QKeySequence("Ctrl+1"), this);
connect(sh, SIGNAL(activated()), this, SLOT(LightUpFirst()));

and the LightUpFirst function does the selecting. Hope that helps!

各自安好 2024-12-05 20:12:47

我想我现在已经可以使用了。更改列表的 rootIndex 后,我必须等待模型完成其工作。在从模型中获取directoryLoaded 信号之前,我不会在新目录中设置currentIndex。现在重点介绍作品。模型中的数据未排序,因此 row=0 & col=0 毕竟不是列表中的第一项,但那是另一个主题:)

编辑:今晚对此进行了更多修改,并添加了最后的修改。

const QString rp = "/home/anders/src";

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath(rp);

    list = new QListView;
    list->setModel(model);
    list->show();

    connect(model,
            SIGNAL(directoryLoaded(QString)),
            this,
            SLOT(model_directoryLoaded(QString)));

    QTimer::singleShot(2000, this, SLOT(changeRoot()));
}

void MainWindow::model_directoryLoaded(QString path)
{
    qDebug() << "loaded" << path;
    model->sort(0, Qt::AscendingOrder);
    list->setCurrentIndex(model->index(0, 0, list->rootIndex()));
}

void MainWindow::changeRoot()
{
    qDebug() << "changeRoot";
    model->setRootPath(rp + "/trunk");
    list->setRootIndex(model->index(rp + "/trunk"));
}

MainWindow::~MainWindow()
{
    delete list;
    delete model;
    delete ui;
}

I think I have it working now. After changing the rootIndex of the list, I have to wait for the model to do its work. I don't set the currentIndex in the new directory until I get the directoryLoaded signal from the model. Now highlighting works. The data from the model is not sorted, so row=0 & col=0 is not the first item in the list after all, but that's another topic :)

Edit: fiddled a bit more with this tonight, and added the final touches.

const QString rp = "/home/anders/src";

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    model = new QFileSystemModel;
    model->setRootPath(rp);

    list = new QListView;
    list->setModel(model);
    list->show();

    connect(model,
            SIGNAL(directoryLoaded(QString)),
            this,
            SLOT(model_directoryLoaded(QString)));

    QTimer::singleShot(2000, this, SLOT(changeRoot()));
}

void MainWindow::model_directoryLoaded(QString path)
{
    qDebug() << "loaded" << path;
    model->sort(0, Qt::AscendingOrder);
    list->setCurrentIndex(model->index(0, 0, list->rootIndex()));
}

void MainWindow::changeRoot()
{
    qDebug() << "changeRoot";
    model->setRootPath(rp + "/trunk");
    list->setRootIndex(model->index(rp + "/trunk"));
}

MainWindow::~MainWindow()
{
    delete list;
    delete model;
    delete ui;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文