上一章我们详细了解了QStringListModel。本章我们将再来介绍另外一个内置模型:QFileSystemModel。看起来,QFileSystemModelQStringListModel要复杂得多;事实也是如此。但是,虽然功能强大,QFileSystemModel的使用还是简单的。

让我们从 Qt 内置的模型说起。实际上,Qt 内置了两种模型:QStandardItemModelQFileSystemModelQStandardItemModel是一种多用途的模型,能够让列表、表格、树等视图显示不同的数据结构。这种模型会将数据保存起来。试想一下,列表和表格所要求的数据结构肯定是不一样的:前者是一维的,后者是二维的。因此,模型需要保存有实际数据,当视图是列表时,以一维的形式提供数据;当视图是表格时,以二维的形式提供数据。QFileSystemModel则是另外一种方式。它的作用是维护一个目录的信息。因此,它不需要保存数据本身,而是保存这些在本地文件系统中的实际数据的一个索引。我们可以利用QFileSystemModel显示文件系统的信息、甚至通过模型来修改文件系统。

QTreeView是最适合应用QFileSystemModel的视图。下面我们看一段代码:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
FileSystemWidget::FileSystemWidget(QWidget *parent) :
    QWidget(parent)
{
    model = new QFileSystemModel;
    model->setRootPath(QDir::currentPath());
 
    treeView = new QTreeView(this);
    treeView->setModel(model);
    treeView->setRootIndex(model->index(QDir::currentPath()));
 
    QPushButton *mkdirButton = new QPushButton(tr("Make Directory..."), this);
    QPushButton *rmButton = new QPushButton(tr("Remove"), this);
    QHBoxLayout *buttonLayout = new QHBoxLayout;
    buttonLayout->addWidget(mkdirButton);
    buttonLayout->addWidget(rmButton);
 
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(treeView);
    layout->addLayout(buttonLayout);
 
    setLayout(layout);
    setWindowTitle("File System Model");
 
    connect(mkdirButton, SIGNAL(clicked()),
            this, SLOT(mkdir()));
    connect(rmButton, SIGNAL(clicked()),
            this, SLOT(rm()));
}

构造函数很简单,我们首先创建了QFileSystemModel实例,然后将其作为一个QTreeView的模型。注意我们将QFileSystemModel的根目录路径设置为当前目录。剩下来的都很简单,我们添加了按钮之类,这些都不再赘述。对于 treeView 视图,我们使用了setRootIndex()对模型进行过滤。我们可以尝试一下,去掉这一句的话,我们的程序会显示整个文件系统的目录;而这一句的作用是,从模型中找到 QDir::currentPath()所对应的索引,然后显示这一位置。也就是说,这一语句的作用实际是设置显示哪个目录。我们会在后面的章节中详细讨论index()函数。

现在,我们可以运行以下程序看看界面:

虽然我们基本一行代码都没写(有关文件系统的代码都没有写),但是从运行截图可以看出,QFileSystemModel完全将所能想到的东西——名称、大小、类型、修改时间等全部显示出来,可见其强大之处。

下面是mkdir()槽函数:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void FileSystemWidget::mkdir()
{
    QModelIndex index = treeView->currentIndex();
    if (!index.isValid()) {
        return;
    }
    QString dirName = QInputDialog::getText(this,
                                            tr("Create Directory"),
                                            tr("Directory name"));
    if (!dirName.isEmpty()) {
        if (!model->mkdir(index, dirName).isValid()) {
            QMessageBox::information(this,
                                     tr("Create Directory"),
                                     tr("Failed to create the directory"));
        }
    }
}

正如代码所示,首先我们获取选择的目录。后面这个isValid()判断很重要,因为默认情况下是没有目录被选择的,此时路径是非法的,为了避免程序出现异常,必须要有这一步判断。然后弹出对话框询问新的文件夹名字,如果创建失败会有提示,否则就是创建成功。这时候你会发现,硬盘的实际位置的确创建了新的文件夹。

下面则是rm()槽函数:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void FileSystemWidget::rm()
{
    QModelIndex index = treeView->currentIndex();
    if (!index.isValid()) {
        return;
    }
    bool ok;
    if (model->fileInfo(index).isDir()) {
        ok = model->rmdir(index);
    } else {
        ok = model->remove(index);
    }
    if (!ok) {
        QMessageBox::information(this,
                         tr("Remove"),
                         tr("Failed to remove %1").arg(model->fileName(index)));
    }
}

这里同样需要先检测路径是否合法。另外需要注意的是,目录和文件的删除不是一个函数,需要调用isDir()函数检测。这一步在代码中有很清楚的描述,这里就不再赘述了。

实际上,我们这里不需要十分担心QFileSystemModel的性能问题,因为它会启动自己的线程进行文件夹扫描,不会发生因扫描文件夹而导致的主线程阻塞的现象。另外需要注意的是,QFileSystemModel会对模型的结果进行缓存,如果你要立即刷新结果,需要通知QFileSystemWatcher类。

如果仔细查看就会发现,我们的视图不能排序不能点击列头。为此,我们可以使用下面代码:

 
 
1
2
3
4
5
6
7
8
treeView->header()->setStretchLastSection(true);
treeView->header()->setSortIndicator(0, Qt::AscendingOrder);
treeView->header()->setSortIndicatorShown(true);
#if QT_VERSION >= 0x050000
    treeView->header()->setSectionsClickable(true);
#else
    treeView->header()->setClickable(true);
#endif

这是 Qt 中视图类常用的一种技术:如果我们要修改有关列头、行头之类的位置,我们需要从视图类获取到列头对象,然后对其进行设置。正如代码中所显示的那样。注意上面代码片段的最后一部分,我们使用一个条件判断来确定 Qt4 与 Qt5 的不同。

现在我们简单介绍了有关两个常用的模型类:QStringListModel 和 QFileSystemModel。下一章,我们将在此基础上详细介绍模型的相关细节。

Qt 学习之路:QFileSystemModel的更多相关文章

  1. Qt 学习之路 2(44):QFileSystemModel

    Home / Qt 学习之路 2 / Qt 学习之路 2(44):QFileSystemModel Qt 学习之路 2(44):QFileSystemModel  豆子  2013年2月21日  Qt ...

  2. Qt 学习之路 2(48):QSortFilterProxyModel

    Qt 学习之路 2(48):QSortFilterProxyModel 豆子 2013年4月11日 Qt 学习之路 2 6条评论 从本章开始,我们将逐步了解有关自定义模型的相关内容.尽管前面我们曾经介 ...

  3. Qt 学习之路 2(46):视图和委托

    Home / Qt 学习之路 2 / Qt 学习之路 2(46):视图和委托 Qt 学习之路 2(46):视图和委托  豆子  2013年3月11日  Qt 学习之路 2  63条评论 前面我们介绍了 ...

  4. Qt 学习之路 2(45):模型

    Home / Qt 学习之路 2 / Qt 学习之路 2(45):模型 Qt 学习之路 2(45):模型  豆子  2013年2月26日  Qt 学习之路 2  23条评论 在前面两章的基础之上,我们 ...

  5. Qt 学习之路 2(41):model/view 架构

    Qt 学习之路 2(41):model/view 架构 豆子 2013年1月23日 Qt 学习之路 2 50条评论 有时,我们的系统需要显示大量数据,比如从数据库中读取数据,以自己的方式显示在自己的应 ...

  6. 《Qt 学习之路 2》目录

    <Qt 学习之路 2>目录 <Qt 学习之路 2>目录  豆子  2012年8月23日  Qt 学习之路 2  177条评论 <Qt 学习之路 2>目录 序 Qt ...

  7. QT学习之路--创建一个对话框

    Q_OBJECT:这是一个宏,凡是定义信号槽的类都必须声明这个宏. 函数tr()全名是QObject::tr(),被他处理过的字符串可以使用工具提取出来翻译成其他语言,也就是做国际化使用. 对于QT学 ...

  8. 转载: Qt 学习之路 2归档

    Qt 学习之路 2归档 http://www.devbean.net/2012/08/qt-study-road-2-catelog/

  9. Qt学习之路

      Qt学习之路_14(简易音乐播放器)   Qt学习之路_13(简易俄罗斯方块)   Qt学习之路_12(简易数据管理系统)   Qt学习之路_11(简易多文档编辑器)   Qt学习之路_10(Qt ...

  10. Qt 学习之路 2

    Qt 学习之路 2 | DevBean Tech World Qt 学习之路 2 Qt 学习之路 2 目录

随机推荐

  1. ASP.NET页面跳转的三种方法比较

    在ASP.NET下,经常需要在页面之间跳转,下面我们来分别介绍一下关于.NET中Response.Redirect(),Sever.Execute(),Server.Transfer() 三种页面跳转 ...

  2. LI 导航

    HTML: <div class="my_nav"> <ul> <li class="tiao cur" id="ord ...

  3. ubuntu 安装 open in teminal

    sudo apt-get install nautilus-open-terminalnautilus -q

  4. python模块之re正则表达式

    41.python的正则表达式      1. python中re模块提供了正则表达式相关操作 字符: . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线或汉字      \W大写代表非\w ...

  5. 简明解释算法中的大O符号

    伯乐在线导读:2009年1月28日Arec Barrwin在StackOverflow上提问,“有没有关于大O符号(Big O notation)的简单解释?尽量别用那么正式的定义,用尽可能简单的数学 ...

  6. Dungeon Master

    poj2251:http://poj.org/problem?id=2251 题意:给你一个三维的立方体,然后给你一个起点,和终点的坐标.然后让你求从起点到终点的最短路程.题解:该题就是求三维的最短路 ...

  7. MySQL使用rand函数实现随机数

    sql 的随机函数newID()和RAND() sql server的随机函数newID()和RAND() SELECT * FROM Northwind..Orders ORDER BY NEWID ...

  8. python locals()和globals()

    Python有两个内置的函数,locals() 和globals(),它们提供了基于字典的访问局部和全局变量的方式. 首先,是关于名字空间的一个名词解释.是枯燥,但是很重要,所以要耐心些.Python ...

  9. 【高精度】NCPC 2014 C catalansqure

    题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1789 题目大意: 求大卡特兰数..公式如下.输入n求Sn(n<=5000) 题目 ...

  10. MVVM模式中WPF数据的完全绑定

    一:截图,描述:将后台代码的姓名.年龄绑定到文本框,单击”增加年龄“--年龄自+1,单击”显示年龄“--弹出年龄的显示对话框,实现了从文本框修改年龄和后台更改年龄并显示到文本框 运行结果和解决方案管理 ...