当前位置: 首页 > news >正文

QT M/V架构开发实战:QFileSystemModel介绍

目录

    • @[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内部集成,没有直接禁用选项,可能需要自定义模型)。

本次分享就到这里了,如果有什么错误的话请指正,或者有什么疑问的,也可以在评论区一起探讨!


文章转载自:

http://Dh6OqhDF.nLygm.cn
http://qL0dN6mu.nLygm.cn
http://S1eEeXa4.nLygm.cn
http://KxCoyhmH.nLygm.cn
http://XgmTJj0S.nLygm.cn
http://uda9RVDu.nLygm.cn
http://TZ0LEk9k.nLygm.cn
http://JoQbBTuB.nLygm.cn
http://6hRFi0WJ.nLygm.cn
http://uoImJhs9.nLygm.cn
http://ri5stg7S.nLygm.cn
http://XzBuaYLZ.nLygm.cn
http://nn03PweO.nLygm.cn
http://PbzqKb8S.nLygm.cn
http://doinVpBk.nLygm.cn
http://k8dqT6HM.nLygm.cn
http://oLi57EHj.nLygm.cn
http://rjzGueyh.nLygm.cn
http://ok63k3Vg.nLygm.cn
http://TTBUOCrJ.nLygm.cn
http://hEsyaUmy.nLygm.cn
http://hpdzPXCm.nLygm.cn
http://cGhfC928.nLygm.cn
http://FlDbzl3K.nLygm.cn
http://2rYIMaui.nLygm.cn
http://14d3q8r0.nLygm.cn
http://4mCEbwZo.nLygm.cn
http://Q4v3kZx4.nLygm.cn
http://UdHoDujF.nLygm.cn
http://chpJcRDf.nLygm.cn
http://www.dtcms.com/a/379681.html

相关文章:

  • 基于POI-TL实现动态Word模板的数据填充:【散点图】特殊处理方案
  • Chrome插件开发入门技术文章大纲
  • 新手向:如何高效使用AI技术
  • iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
  • Docker网络实战:容器通信与隔离之道
  • AI 赋能云端运维:基于 MCP 协议深度集成 Codebuddy CLI 与腾讯云 Lighthouse 的实战全解
  • 《从 0 建立测试开发认知:先搞懂 “是什么”,再学 “怎么做”》
  • Flink1.17.0集群的搭建
  • #C语言——刷题攻略:牛客编程入门训练(十二):攻克 循环控制(四)、循环输出图形(一),轻松拿捏!
  • 面试经典150题[029]:三数之和(LeetCode 15)
  • Ubuntu 24.04 搭建k8s 1.33.4
  • 从数字后端角度谈谈occ电路(一)
  • Hadoop简介:分布式系统的基石与核心架构详解
  • [数据结构] 优先级队列(堆)
  • 计算机毕业设计 基于深度学习的酒店评论文本情感分析研究 Python毕业设计项目 Hadoop毕业设计选题 机器学习选题【附源码+文档报告+安装调试】
  • 数据结构 Java对象的比较
  • EDID 数据结构解析与编辑工具:校验和计算、厂商/设备名编解码、物理地址读写、颜色与时序信息提取
  • 龙蜥8.10中spark各种集群及单机模式的搭建spark3.5.6(基于hadoop3.3.6集群)
  • Hadoop MapOutputBuffer:Map高性能核心揭秘
  • Kubernetes 弹性伸缩:深入讲解 HPA 和 VPA
  • 代理服务器是什么?怎么选择?
  • java Redisson 实现限流每秒/分钟/小时限制N个请求 -V2.0
  • 高并发、低延迟全球直播系统架构
  • zookeeper是啥
  • 短波红外相机在机器视觉检测方向的应用
  • 阿里云国际代理:如何利用RDS构建高可用、可扩展的数据库架构
  • 【Python】通俗理解反向传播
  • RFID技术在半导体电子货架上的应用方案
  • Windows 安装 Redis 教程
  • CMake 全流程开发实战:从零开始掌握C++项目构建、测试到一键分发的完整解决方案​