Qt学习之路(43): QDirModel

简介:
今天我们来看一个很有用的model:QDirModel。这个model允许我们在view中显示操作系统的目录结构。这次让我们先来看看运行结果:
 
 
这个界面很熟悉吧?不过这可不是由QFileDialog打开的哦,这是我们自己实现的。而提供这种实现支持的,就是QDirModel和QTreeView。我们来看一下代码。
 
mytreeview.h
#ifndef MYLISTVIEW_H 
#define MYLISTVIEW_H 
 
#include <QtGui> 
 
class MyTreeView :  public QWidget 

        Q_OBJECT 
public
        MyTreeView(); 
 
private
        QDirModel *model; 
        QTreeView *treeView; 
 
private slots: 
         void mkdir(); 
         void rm(); 
}; 
 
#endif  // MYLISTVIEW_H
 
mytreeview.cpp
#include  "mylistview.h" 
 
MyTreeView::MyTreeView() 

        model =  new QDirModel; 
        model->setReadOnly( false); 
        model->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name); 
 
        treeView =  new QTreeView; 
        treeView->setModel(model); 
        treeView->header()->setStretchLastSection( true); 
        treeView->header()->setSortIndicator(0, Qt::AscendingOrder); 
        treeView->header()->setSortIndicatorShown( true); 
        treeView->header()->setClickable( true); 
 
        QModelIndex index = model->index(QDir::currentPath()); 
        treeView->expand(index); 
        treeView->scrollTo(index); 
        treeView->resizeColumnToContents(0); 
 
        QHBoxLayout *btnLayout =  new QHBoxLayout; 
        QPushButton *createBtn =  new QPushButton(tr( "Create Directory...")); 
        QPushButton *delBtn =  new QPushButton(tr( "Remove")); 
        btnLayout->addWidget(createBtn); 
        btnLayout->addWidget(delBtn); 
        QVBoxLayout *mainLayout =  new QVBoxLayout( this); 
        mainLayout->addWidget(treeView); 
        mainLayout->addLayout(btnLayout); 
         this->setLayout(mainLayout); 
 
        connect(createBtn, SIGNAL(clicked()),  this, SLOT(mkdir())); 
        connect(delBtn, SIGNAL(clicked()),  this, SLOT(rm())); 

 
void MyTreeView::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")); 
                } 
        } 

 
void MyTreeView::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))); 
        } 

 
构造函数中,首先我们创建了QDirModel的一个对象,并且设置ReadOnly为false,也就是说我们可以对其进行修改。而下一个setSorting()函数是对其进行排序,排序的依据也很清楚:文件夹优先(QDir::DirsFirst),忽略大小写(QDir::IgnoreCase),而且是根据名字排序(QDir::Name)。更多的规则组合可以参见 API 文档了。
 
然后我们创建一个QTreeView实例,并且把model设置为刚刚的QDirModel实例。然后我们开始设置QTreeView的相关属性。首先把stretchLastSection设置为true。如果把这个属性设置为true,就是说,当QTreeView的宽度大于所有列宽之和时,最后一列的宽度自动扩展以充满最后的边界;否则就让最后一列的宽度保持原始大小。第二个setSortIndicator()函数是设置哪一列进行排序。由于我们前面设置了model是按照名字排序,所以我们这个传递的第一个参数是0,也就是第1列。setSortIndicatorShown()函数设置显示列头上面的排序小箭头。setClickable(true)则允许鼠标点击列头。这样,我们的QTreeView就设置完毕了。最后,我们通过QDir::currentPath()获取当前exe文件运行时路径,并把这个路径当成程序启动时显示的路径。expand()函数即展开这一路径;scrollTo()函数是把视图的视口滚动到这个路径的位置;resizeColumnToContents()是要求把列头适应内容的宽度,也就是不产生...符号。这样,我们就通过一系列的参数设置好了QTreeView,让它能够为我们展示目录结构。
 
至于后面的两个slot,其实并不能理解。第一个mkdir()函数就是创建一个文件夹。
 
void MyTreeView::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()的判断很重要,因为默认情况下是没有目录被选择的,此时这个路径是非法的,为了避免程序出现异常,必须要有这一步判断。然后会弹出对话框询问新的文件夹名字,如果创建失败会有提示,否则就是创建成功。这时候你就可以到硬盘上的实际位置看看啦!
 
删除目录的代码也很类似:
 
void MyTreeView::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()函数检测。这一步在代码中有很清楚的描述,这里就不再赘述了。
 
注意,QDirModel 在最新版 Qt 中已经不建议使用了。文档中说使用 QFileSystemModel 代替。由于这两者的函数几乎一样,所以就没有对代码进行修改。与QDirModel不同的是,QFileSystemModel会启动自己的线程进行文件夹的扫描,因此不会发生因扫描文件夹而导致的主线程阻塞的现象。另外,无论 QDirModel还是QFileSystemModel都会对model结果进行缓存,如果你要立即刷新结果,前者提供了refresh()函数,而后者会通知QFileSystemWatcher类。


本文转自 FinderCheng 51CTO博客,原文链接:
http://blog.51cto.com/devbean/265658
相关文章
|
Linux C语言
[学习][笔记] qt5 从入门到入坟:<一>hello Qt
[学习][笔记] qt5 从入门到入坟:<一>hello Qt
134 0
|
定位技术 Go 开发工具
dynamic-situational-awareness-qt学习记录
本文是作者yantuguiguziPGJ关于dynamic-situational-awareness-qt学习记录的分享,介绍了在Qt学习过程中发现的qml资源丰富的代码仓库,并提供了资源路径和相关的安装、配置步骤,涉及的内容有数字地球、GIS纹理等,同时提供了相关链接和git命令来克隆代码仓库和ArcGIS Runtime SDK for Qt的安装说明。
121 8
Qt中的信号与槽如何学习?(包括自定义信号)这篇文章告诉你
以现实中的事件来举例的话,例如有两把不同颜色的信号枪,分别是红色,绿色,打响不通颜色的信号枪会触发不同的槽发生,比如说打响红色这个人就跑步,绿色就走步,但是还有一个很重要的机制,那就是连接,我们需要把信号枪去跟这个人的动作连接起来。 如果上面理解没问题的话我们可以把信号和槽看成两个工具,我们最重要的是如何去把这两个工具连接起来。 它的作用可以让我们更加灵活的去使用不同窗口间的切换以及某些事件的连接。
297 0
|
开发者
Qt中的事件该如何学习?(附带案例)
事件是Qt中比较重要的一部分,在初期如果理解不当学习可能会比较困难,这里提一嘴当初教我的那位老师水平是真的高,让我很轻易的就理解了事件的概念。 在平时我们见到那些界面上的某些快捷键就有可能是事件做的,例如ESC关闭窗口,Enter提交或者登录这种类似的,这也是事件的强大之处。
588 0
|
API
QT学习—属于自己的串口调试助手
本文详细介绍了如何编写一个属于自己的串口助手。
2126 3
|
编解码 开发框架 Linux
Qt入门学习
学习Qt并使用Qt
455 0
Qt入门学习
[学习][笔记] qt5 从入门到入坟:《零》vs开发qt项目
[学习][笔记] qt5 从入门到入坟:《零》vs开发qt项目
188 0
|
定位技术 图形学
[学习][笔记] qt5 从入门到入坟:<13>基于GraphicsViewFrame的贪吃蛇实现
[学习][笔记] qt5 从入门到入坟:<13>基于GraphicsViewFrame的贪吃蛇实现
181 0
|
图形学
[学习][笔记] qt5 从入门到入坟:<12>Graphics View Framework
[学习][笔记] qt5 从入门到入坟:<12>Graphics View Framework
186 0
|
编解码 图形学
[学习][笔记] qt5 从入门到入坟:<11>绘制设备
[学习][笔记] qt5 从入门到入坟:<11>绘制设备
142 0