今天我們來看一個很有用的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()
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()函數就是建立一個檔案夾。
}
正如它的代碼所示,首先擷取選擇的目錄。後面這個isValid()的判斷很重要,因為預設情況下是沒有目錄被選擇的,此時這個路徑是非法的,為了避免程式出現異常,必須要有這一步判斷。然後會彈出對話框詢問新的檔案夾名字,如果建立失敗會有提示,否則就是建立成功。這時候你就可以到硬碟上的實際位置看看啦!
删除目錄的代碼也很類似:
同樣需要實作檢測路徑是否合法。另外需要注意的是,目錄和檔案的删除不是一個函數,需要調用isDir()函數檢測。這一步在代碼中有很清楚的描述,這裡就不再贅述了。
注意,QDirModel 在最新版 Qt 中已經不建議使用了。文檔中說使用 QFileSystemModel 代替。由于這兩者的函數幾乎一樣,是以就沒有對代碼進行修改。與QDirModel不同的是,QFileSystemModel會啟動自己的線程進行檔案夾的掃描,是以不會發生因掃描檔案夾而導緻的主線程阻塞的現象。另外,無論 QDirModel還是QFileSystemModel都會對model結果進行緩存,如果你要立即重新整理結果,前者提供了refresh()函數,而後者會通知QFileSystemWatcher類。
本文轉自 FinderCheng 51CTO部落格,原文連結:
http://blog.51cto.com/devbean/265658