目錄
- @[TOC](目錄)
- 前言
- 一、QFileSystemModel初步介紹
- 二、基本功能
- 1.創建
- 2.基本屬性與方法
- 三、示例(簡單的文件瀏覽器)
- 四、性能注意事項
目錄
- @[TOC](目錄)
- 前言
- 一、QFileSystemModel初步介紹
- 二、基本功能
- 1.創建
- 2.基本屬性與方法
- 三、示例(簡單的文件瀏覽器)
- 四、性能注意事項
前言
本文主要介紹的是使用代碼生成的情況下對控件的介紹,包括擁有的功能及能修改的樣式,也會說明在qtdesiner拖拽控件生成和使用代碼生成控件的區別(如果有的話,遇到了的會說),此版本不屬于最終版本,以后遇到什么新奇的點會繼續更新!本文基于QT官方的文檔進行的編寫,QT版本為qt 5.14.0,編寫環境為Windows11。不得不說官方文檔真是個好東西,有時候有些不會的上去一看就能有靈感解決了,可惜沒有中文版本的。
一、QFileSystemModel初步介紹
QFileSystemModel是 Qt 提供的一個極其強大且實用的模型類,專門用于展示和操作本地文件系統。它抽象了文件系統的層次結構(目錄樹),并將其完美地適配到 Qt 的 Model-View 框架中,使得在 QTreeView、QListView或 QTableView中構建文件瀏覽器變得非常簡單。
?核心思想:??
QFileSystemModel繼承自 QAbstractItemModel(更具體地說,通常是 QDirModel的替代者,后者已廢棄)。
將本地文件系統的目錄結構映射為一個樹狀模型。
每個文件或目錄對應模型中的一個項 (QModelIndex)。
提供了豐富的接口來獲取文件屬性(名稱、路徑、大小、類型、修改時間、權限、圖標等)。
支持??異步加載??(默認),這意味著在后臺線程中讀取目錄內容,避免阻塞 UI 線程,尤其是在處理大型目錄或網絡驅動器時體驗更流暢。
自動監聽文件系統的變化(通過 QFileSystemWatcher),并在文件或目錄被添加、刪除、重命名或修改時??自動更新模型和視圖??。
讀寫操作(需謹慎):?? 支持通過模型接口重命名、刪除文件/目錄(需要權限)。
二、基本功能
1.創建
#include <QFileSystemModel>QFileSystemModel *model = new QFileSystemModel(parent);
2.基本屬性與方法
1)設置根路徑
關鍵一步??!告訴模型從哪個目錄開始構建樹狀結構。視圖(如 QTreeView)通常會自動展開并顯示此根路徑下的內容
// 設置根路徑為當前用戶的主目錄
model->setRootPath(QDir::homePath());// 設置根路徑為 C 盤 (Windows)
model->setRootPath("C:/");// 設置根路徑為根目錄 (Linux/macOS)
model->setRootPath("/");
2)連接視圖
QTreeView *treeView = new QTreeView;
treeView->setModel(model); // 設置模型// 通常,你會將視圖的根索引設置為模型的根路徑索引
treeView->setRootIndex(model->index(model->rootPath()));
3)獲取文件信息 (通過 QModelIndex或 QFileInfo)
使用 data()函數 (指定角色)
QModelIndex index = ...; // 例如 treeView->currentIndex() 或從選擇模型獲取// 文件/目錄名 (DisplayRole)
QString name = model->data(index, Qt::DisplayRole).toString();// 完整路徑 (FilePathRole - 這是 QFileSystemModel 特有的便捷角色)
QString fullPath = model->data(index, QFileSystemModel::FilePathRole).toString();
// 或者使用標準的 ToolTipRole 有時也會顯示路徑 (取決于視圖)
QString toolTipPath = model->data(index, Qt::ToolTipRole).toString();// 文件大小 (SizeRole) - 目錄通常返回 -1 或 0
qint64 size = model->data(index, QFileSystemModel::SizeRole).toLongLong();// 文件類型 (TypeRole) - 例如 "JPEG image", "Text Document", "Folder"
QString type = model->data(index, QFileSystemModel::TypeRole).toString();// 最后修改時間 (LastModifiedRole)
QDateTime lastModified = model->data(index, QFileSystemModel::LastModifiedRole).toDateTime();// 圖標 (DecorationRole)
QIcon icon = model->data(index, Qt::DecorationRole).value<QIcon>();
使用 fileInfo()(更直接)
QFileInfo fileInfo = model->fileInfo(index);
QString name = fileInfo.fileName();
QString fullPath = fileInfo.absoluteFilePath();
qint64 size = fileInfo.size();
bool isDir = fileInfo.isDir();
bool isFile = fileInfo.isFile();
QDateTime lastModified = fileInfo.lastModified();
QFile::Permissions perms = fileInfo.permissions();
// ... 使用 QFileInfo 的所有豐富接口 ...
4)過濾顯示的文件 (setFilter)
使用 QDir::Filters枚舉組合來指定哪些文件和目錄應該被顯示。QDir::NoDotAndDotDot:通常建議加上,以排除 .(當前目錄) 和 …(父目錄) 項。
// 只顯示目錄 (不顯示文件)
model->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);// 顯示所有文件和目錄 (默認)
model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); // 通常排除 "." 和 ".."// 顯示所有文件 (包括隱藏文件) 和目錄
model->setFilter(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot);// 只顯示 .txt 和 .cpp 文件以及所有目錄
model->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
model->setNameFilters(QStringList() << "*.txt" << "*.cpp");
model->setNameFilterDisables(false); // true: 隱藏不匹配項; false: 顯示但不匹配 (通常false)
5)排序 (sort)
視圖的列順序通常是:0=名稱, 1=大小, 2=類型, 3=修改日期 (取決于 headerData實現)。
// 按名稱排序 (默認)
treeView->setSortingEnabled(true); // 允許用戶點擊表頭排序
treeView->sortByColumn(0, Qt::AscendingOrder); // 按第0列(名稱)升序// 在代碼中指定排序 (例如按大小降序)
model->sort(2, Qt::DescendingOrder); // 假設大小在第2列 (需要根據視圖的列定義)
6)監聽目錄加載完成 (directoryLoaded信號)
由于加載是異步的,如果你需要在某個目錄內容加載完成后執行操作(如展開、選擇特定項),可以連接此信號。
connect(model, &QFileSystemModel::directoryLoaded,this, [this, model](const QString &path) {if (path == targetDirectoryPath) {// 找到并選中目標文件,或展開目錄等QModelIndex targetIndex = model->index(targetFilePath);treeView->setCurrentIndex(targetIndex);treeView->scrollTo(targetIndex);}
});
model->setRootPath(targetDirectoryPath); // 或者調用 fetchMore(index) 觸發加載
7)文件操作 (需謹慎!)
重命名 (setData)
QModelIndex oldIndex = ...;
bool success = model->setData(oldIndex, "NewFileName.txt", Qt::EditRole);
// 成功會觸發 dataChanged 信號,視圖更新
// 失敗通常是因為權限不足或文件正在使用
創建目錄 (mkdir)
QModelIndex parentDirIndex = ...; // 要在哪個目錄下創建
QModelIndex newDirIndex = model->mkdir(parentDirIndex, "NewFolderName");
if (!newDirIndex.isValid()) {// 創建失敗 (權限、重名等)
}
?刪除 (remove)
QModelIndex indexToRemove = ...;
bool success = model->remove(indexToRemove);
if (!success) {// 刪除失敗 (權限、文件不存在等)
}
注意事項:?? 這些操作會??直接作用于真實文件系統??!務必進行錯誤處理,并考慮提供用戶確認(如刪除確認對話框)。對于復雜的文件操作(復制、移動),通常建議使用 QFile、QDir或 QProcess調用系統命令,而不是依賴模型的 remove或 setData。
三、示例(簡單的文件瀏覽器)
#include <QApplication>
#include <QSplitter>
#include <QTreeView>
#include <QListView>
#include <QFileSystemModel>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 創建分割器窗口QSplitter *splitter = new QSplitter;// 創建模型QFileSystemModel *model = new QFileSystemModel;model->setRootPath(QDir::homePath()); // 設置根路徑model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); // 顯示所有項// 創建樹視圖 (左側 - 目錄樹)QTreeView *treeView = new QTreeView(splitter);treeView->setModel(model);treeView->setRootIndex(model->index(model->rootPath())); // 設置視圖根索引treeView->setSortingEnabled(true); // 允許排序treeView->setAnimated(true); // 展開折疊動畫treeView->setIndentation(20); // 縮進// 創建列表視圖 (右側 - 當前目錄內容)QListView *listView = new QListView(splitter);listView->setModel(model);listView->setViewMode(QListView::IconMode); // 圖標模式listView->setIconSize(QSize(64, 64)); // 圖標大小// 連接樹視圖的點擊信號,更新列表視圖的根索引QObject::connect(treeView, &QTreeView::clicked,[model, listView](const QModelIndex &index) {if (model->isDir(index)) {listView->setRootIndex(index); // 點擊目錄,在列表視圖中顯示其內容}});// 初始設置列表視圖顯示根目錄內容listView->setRootIndex(model->index(model->rootPath()));splitter->setWindowTitle("Simple File Browser");splitter->resize(800, 600);splitter->show();return app.exec();
}
四、性能注意事項
?1、大型目錄:?? 加載包含成千上萬文件的目錄會消耗內存和時間。考慮:
使用 QDir手動加載部分項(但這失去了 MV 自動更新的優勢)。
使用 QSortFilterProxyModel進行過濾,減少顯示項**。
提示用戶目錄很大。
2、??網絡驅動器/慢速介質:?? 異步加載尤為重要。directoryLoaded信號有助于知道何時加載完成。
??3、文件監控:?? QFileSystemWatcher可能會消耗資源(尤其是在 Windows 上監控大量文件)。如果不需要實時更新,可以考慮禁用(但 QFileSystemModel內部集成,沒有直接禁用選項,可能需要自定義模型)。
本次分享就到這里了,如果有什么錯誤的話請指正,或者有什么疑問的,也可以在評論區一起探討!