Qt-QFileIconProvider(获取文件图标、类型)

本文介绍了使用Qt的QFileIconProvider及Windows API获取文件和文件夹图标与类型的方法,并对比了两者之间的主要区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Qt中获取系统图标、类型是通过QFileIconProvider来实现的,具体如下:

 

一、Qt获取系统文件图标

1、获取文件夹图标

 QFileIconProvider icon_provider;

 QIcon icon = icon_provider.icon(QFileIconProvider::Folder);

 

2、获取指定文件图标

QFileInfo file_info(name);
QFileIconProvider icon_provider;
QIcon icon = icon_provider.icon(file_info);

 

二、Windows编程中获取系统图标、类型:

QIcon Setting::getFileIcon(QString file_name)
{
 QIcon file_icon = QIcon(":/icon/file");
 if(!file_name.isEmpty())
 {
  //获取后缀
  std::string str = "file";
  int index = file_name.lastIndexOf(".");
  if(index >= 0)
  {
   QString suffix = file_name.mid(index); 

   //将QString转化为std::string
   str = suffix.toUtf8().constData(); //std::string((const char *)path.toLocal8Bit())   path.toLatin1().data();
  }

  LPCSTR name = str.c_str();

  
  SHFILEINFOA info;
  if(SHGetFileInfoA(name,
   FILE_ATTRIBUTE_NORMAL,
   &info,
   sizeof(info),
   SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_USEFILEATTRIBUTES))
  {
   HICON icon = info.hIcon;
   file_icon = QIcon(QPixmap::fromWinHICON(icon));
  }
 }

 return file_icon;
}

 

QString Setting::getFileType(QString file_name)
{
 QString file_type = QString("file");
 if(!file_name.isEmpty())
 {
  //获取后缀
  std::string str = "file";
  int index = file_name.lastIndexOf(".");
  if(index >= 0)
  {
   QString suffix = file_name.mid(index); 

   //将QString转化为std::string
   str = suffix.toUtf8().constData();
  }

  LPCSTR name = str.c_str();

  
  SHFILEINFOA info;
  if(SHGetFileInfoA(name,
   FILE_ATTRIBUTE_NORMAL,
   &info,
   sizeof(info),
   SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES))
  {
   std::string type = info.szTypeName;
   file_type = type.c_str();
  }
 }

 return file_type;
}

 

QIcon Setting::getFolderIcon()
{
 QIcon folder_icon = QIcon(":/icon/folder");

 //将QString转化为std::string
 std::string str = "folder";
 LPCSTR name = str.c_str();

 
 SHFILEINFOA info;
 if(SHGetFileInfoA(name,
  FILE_ATTRIBUTE_DIRECTORY,
  &info,
  sizeof(info),
  SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_USEFILEATTRIBUTES))
 {
  HICON h_icon = info.hIcon;

  folder_icon = QIcon(QPixmap::fromWinHICON(h_icon)); 
 }

 return folder_icon;
}

 

QString Setting::getFolderType()
{
 QString folder_type = QString("folder");
 std::string str = "folder";
 LPCSTR name = str.c_str();

 
 SHFILEINFOA info;
 if(SHGetFileInfoA(name,
  FILE_ATTRIBUTE_DIRECTORY,
  &info,
  sizeof(info),
  SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES))
 {
  std::string type = info.szTypeName;
  folder_type = type.c_str();
 }

 return folder_type;
}

 

效果图:

Qt之QFileIconProvider(获取文件图标、类型)

 

    两种方式最大的区别是什么呢?

    可以参考这篇文章—QFileIconProvider, Getting icon for non-existent file (based on extension)!诸如所言,Qt所提供的获取图标的方法是本地已存在的文件,如果要通过扩展名来获取图标则需要自己来虚拟构造本地文件,而在数据量较大的情况下往往会影响性能。这(通过扩展名获取图标、类型)可以通过Windows API来实现,即方法二。

<think>我们正在处理用户的问题:在Qt中通过文件后缀名获取本地系统图标。根据引用资料,QtQFileIconProvider默认只能为本地已存在的文件提供图标。如果文件不存在,我们需要通过其他方式获取图标。引用[1]和[2]提到,可以通过WindowsAPI来实现(方法二),这样可以避免创建临时文件,提高性能。引用[3]提到,如果使用Qt的方法,我们需要创建临时文件(通过扩展名构造临时文件,然后获取图标,再删除临时文件),但不适用于大量文件的情况,因为性能开销大。引用[4]则提到如何通过任意后缀或本地不存在的文件获取图标,步骤与引用[3]似。因此,我们有两种方法:方法一(Qt方式):创建临时文件,使用QFileIconProvider获取图标,然后删除临时文件。适用于少量文件,但大量文件时性能低。方法二(WindowsAPI):直接使用Windows系统API根据扩展名获取图标。这种方法更高效,但只适用于Windows平台。由于用户没有指定平台,但问题中提到了“本地系统图标”,我们假设用户使用的是Windows(因为大多数Qt桌面应用运行在Windows上)。如果用户需要跨平台,则需要考虑其他平台的实现。下面我们分别给出两种方法的实现步骤和示例代码。方法一:使用Qt创建临时文件(不推荐用于大量文件)步骤:1.根据给定的扩展名(如".txt")创建一个临时文件(使用QTemporaryFile)。2.使用QFileIconProvider获取该临时文件图标。3.删除临时文件QTemporaryFile在析构时会自动删除,也可以手动删除)。示例代码: ```cpp#include <QFileIconProvider> #include<QTemporaryFile> #include<QIcon>QIcongetIconByExtension(const QString& extension) {//创建一个临时文件文件名随机,后缀为给定的扩展名QTemporaryFile tempFile(QDir::tempPath() +"/XXXXXX"+ extension);tempFile.setAutoRemove(true); //设置自动删除if(tempFile.open()) {tempFile.close(); //需要关闭文件,因为QFileIconProvider可能会尝试读取它QFileIconProviderprovider;QIcon icon= provider.icon(QFileInfo(tempFile.fileName()));//临时文件会在tempFile离开作用域时自动删除(因为autoRemove=true)return icon;}return QIcon();//失败返回空图标}```方法二:使用Windows API(推荐,高效)步骤:1.使用WindowsAPI中的SHGetFileInfo函数,传入扩展名和标志SHGFI_USEFILEATTRIBUTES| SHGFI_ICON。2.注意:需要包含Windows.h和Shellapi.h。示例代码(仅Windows):```cpp#ifdefined(Q_OS_WIN) #include<Windows.h>#include <Shellapi.h>QIcongetIconByExtensionWin(const QString& extension) {//将QString转换为wchar_t*QString fileExt= "*" +extension;//例如:"*.txt"std::wstringwstr= fileExt.toStdWString();constwchar_t*wcExt= wstr.c_str();SHFILEINFOW sfi ={0};DWORD_PTRret =SHGetFileInfoW(wcExt, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi),SHGFI_USEFILEATTRIBUTES |SHGFI_ICON| SHGFI_SMALLICON);if(ret!=0) {//从HICON创建QIconQIconicon =QIcon(QPixmap::fromImage(QImage::fromHICON(sfi.hIcon)));DestroyIcon(sfi.hIcon);//销毁图标,避免资源泄漏return icon;}return QIcon();} #endif```注意:方法二仅适用于Windows平台,并且需要链接Shell32.lib(在Qt项目中,可以在.pro文件中添加:LIBS+= -lShell32)。跨平台考虑:如果用户需要跨平台,我们可以编写一个函数,在Windows下使用API,在其他平台(如Linux、macOS)使用临时文件的方法(或者寻找其他平台特定的API)。但其他平台的API可能不同,这里我们只提供Windows的实现。总结:对于大量文件的情况,推荐使用方法二(Windows API),因为它不需要创建临时文件,性能更高。对于少量文件或者跨平台需求,可以考虑方法一(但要注意性能问题)。相关问题:1.在Qt中如何根据文件扩展名获取文件类型(而不仅仅是图标)?2.在Linux或macOS下如何高效地根据文件扩展名获取图标?3.如何使用QtQFileIconProvider获取文件图标?4.如何缓存获取到的文件图标以提高性能?</think>### Qt 根据文件扩展名获取本地系统图标Qt 中通过文件扩展名获取系统图标时,核心挑战在于 `QFileIconProvider` 默认只能为**实际存在的文件**提供图标。以下是两种高效解决方案: #### 方法一:Windows API 实现(推荐) ```cpp #include <Windows.h> #include <Shellapi.h> QIcon getIconByExtension(const QString& ext) { // 构造虚拟文件名(如 "*.txt") wchar_t fakeFile[MAX_PATH]; wcscpy_s(fakeFile, L"*"); ext.toWCharArray(fakeFile + 1); // 追加扩展名 SHFILEINFOW sfi{}; const DWORD flags = SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES; if (SHGetFileInfoW(fakeFile, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), flags)) { QIcon icon(QPixmap::fromImage(QImage::fromHICON(sfi.hIcon))); DestroyIcon(sfi.hIcon); // 必须释放资源 return icon; } return QIcon(); // 失败返回空图标 } ``` **原理**: - 使用 `SHGFI_USEFILEATTRIBUTES` 标志允许查询不存在的文件 - 通过 `*.ext` 格式直接指定扩展名 - 避免创建临时文件,性能高效[^1][^2] #### 方法二:Qt 临时文件方案(跨平台但低效) ```cpp QIcon getIconByExtensionQt(const QString& ext) { QTemporaryFile tempFile(QDir::tempPath() + "/XXXXXX" + ext); if (tempFile.open()) { tempFile.close(); // 创建物理文件 QFileIconProvider provider; return provider.icon(QFileInfo(tempFile.fileName())); } return QIcon(); } ``` **缺点**: - 每次调用都需创建/删除物理文件 - 大量请求时性能低下[^3][^4] #### 使用示例 ```cpp // 获取 .pdf 图标 QIcon pdfIcon = getIconByExtension(".pdf"); // 在 QListView 中使用 QStandardItem* item = new QStandardItem(pdfIcon, "Document.pdf"); ``` #### 性能优化建议 1. **图标缓存**:建立 `QMap<QString, QIcon>` 缓存扩展名对应的图标 2. **异步加载**:对大量文件使用后台线程获取图标 3. **平台检测**:仅在 Windows 使用 API 方案,其他平台用临时文件法 > 关键提示:Windows API 方案性能显著优于临时文件方案,特别是在处理大量文件时[^1][^2]。临时文件方案虽跨平台,但应避免在文件浏览器等高性能场景使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值