我们在实际工作中,需要读取某个文件的信息,例如要求客户选择某个文件、读取文件信息,这时候我们就需要一个能打开文件的窗口,提供客户选择。QT为此提供了各种方法,例如常用的getOpenFileName()可以读取某个文件的路径、getOpenFileNames()读取多个文件的路径等等。
这些方法都存在QFileDialog类中,并且都是静态函数,你可以直接调用这些函数。
#include
QFileDialog::getOpenFileName();//参数是必须的,被我省略了
QFileDialog::getOpenFileUrl();
QFileDialog::getSaveFileName();
QFileDialog::getSaveFileUrl();
QFileDialog::getExistingDirectory();
QFileDialog::getExistingDirectoryUrl();
QFileDialog::getOpenFileNames();
QFileDialog::getOpenFileUrls();
如果你需要的是某个已经存在的文件的名称,那么选择getOpenFileName()是可行的,它返回的是这个文件的名称,包含路径。是最常用的API,非常方便:
QString runPath = QCoreApplication::applicationDirPath();//获取项目的根路径
QString file_name = QFileDialog::getOpenFileName(this,QStringLiteral("选择文件"),runPath,"Text Files(*.txt)",nullptr,QFileDialog::DontResolveSymlinks);
我们先看下这个函数在QT中是什么样的:
static QString getOpenFileName(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
Options options = Options());
第一个参数parent,用于指定父组件,可以看到QT默认这个参数是可以为空的,如果不想提供父控件,你可以直接写nullptr,但是我建议你写一个父控件,例如this即可。这样选择文件的弹框就可以在父控件中间显示。就像这样,弹框的中心和父控件中心是相同的
第二个参数caption,是对话框的标题,例如上图中的“选择文件”就是这么来的
第三个参数dir,是对话框显示时默认打开的目录,"“不写任何参数,那么会默认打开工程的目录,我一般会写”"或者提供项目的根目录;
第四个参数filter,是对话框的后缀名过滤器,如果不写,那么任何文件都会显示,如果写了会根据过滤器显示;
如果选择的文件是同一个类型,只是后缀不同,用空格隔开就好,例如都是图片,“Files(.jpg .png)”,代表只能选择后缀为jpg或者png的图片
如果选择的文件是不同类型,那么需要多个过滤器,过滤器之间用两个分号分隔,例如 "Image Files(.jpg);;Text Files(.png)";
第五个参数selectedFilter,是默认选择的过滤器,写nullptr就行,因为QT默认也是空,啥也没过滤;
第六个参数options,是对话框的一些参数设定,比如只显示文件夹等等,它的取值是enum QFileDialog::Option,每个选项可以使用 | 运算组合起来。
关于option参数,QT提供了很多种:
enum Option
{
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
DontUseSheet = 0x00000008,
DontUseNativeDialog = 0x00000010,
ReadOnly = 0x00000020,
HideNameFilterDetails = 0x00000040,
DontUseCustomDirectoryIcons = 0x00000080
};
ShowDirsOnly:只在对话框中显示路径,默认是会选择文件和路径的。这个参数对getOpenFileName()是没啥用的,很多人写这个参数基本就是出于习惯而已。如果你没写过滤器,那么它会把所有类型的文件和路径都显示出来;如果你写了过滤器,那么它会把满足过滤器的文件和路径显示出来。
DontResolveSymlinks:不要解析符号链接(符号链接在Windows上不常见,至少我很少见谁在自己电脑上创建符号链接。但是在Linux上很常见)。默认是解析符号链接的,即返回的是符号链接指向的文件的路径。一般不会加这个参数。
符号链接其实类似指针,符号链接是指向某个文件或者路径的一条路径,它是一个独立的文件(指针也是一个独立的地址,指向对象地址的一个地址)。符号链接不依赖于目标文件,如果你操作符号链接,其实就是对目标文件操作;如果你删除符号链接,目标文件不受影响;如果你删除目标文件,符号链接依然存在,但是指向一个不存在的文件(你删除指针指向的对象,但是未将指针指向nullptr或者delete,那么指针就是一个野指针,指向未知地址)
DontConfirmOverwrite:覆盖文件的时候,不要弹框提示是否覆盖,直接覆盖即可。对getOpenFileName()也是没啥用,因为getOpenFileName()需要文件已经存在。
DontUseSheet:不要使用给定的外观。实际这个没啥用了,在QT4.5就不再支持了。不需要关注。
DontUseNativeDialog:不要使用本机的对话框类型。QT默认使用的是本机的对话框类型,例如这种就是win10的,本身已经很好用了。但是如果你想自己设计对话框的背景颜色、字体等等,可以使用这个选项。
如果你使用了这个选项,并且没有提供对应的外观,那么显示如下,并且很丑,当然左边的目录显示会更加清晰:
ReadOnly:只读,顾名思义,表示只能读。对getOpenFileName()也是没啥用。
HideNameFilterDetails:表示是否隐藏文件名过滤器详细信息。这个我没使用过,因为我的过滤器需要过滤的是满足后缀的所有文件,在我这里几乎没啥差异,最多就是显示差异,如下,实际就是加上这个参数,在过滤器之间多了分号;,不加就是空格(有了解的麻烦留言下):
DontUseCustomDirectoryIcons:不要使用自定义目录图标,始终使用默认目录图标。
Windows上没见过允许自定义图标,QT解释是:某些平台允许用户设置其他图标,自定义图标查找会对网络或可移动驱动器产生很大的性能影响。因此基于性能考虑,加上这个选项。
QString runPath = QCoreApplication::applicationDirPath();
QUrl file_name = QFileDialog::getOpenFileUrl(this,QStringLiteral("选择路径"),runPath,"Text Files(*.txt *.png)",nullptr,QFileDialog::DontUseCustomDirectoryIcons);
getOpenFileUrl()和getOpenFileName()的用法几乎一样,几乎没差别。唯一的不同就是getOpenFileUrl()支持选择远程的文件,就是它的第7个参数:
static QUrl getOpenFileUrl(QWidget *parent = nullptr,
const QString &caption = QString(),
const QUrl &dir = QUrl(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
Options options = Options(),
const QStringList &supportedSchemes = QStringList());
supportedSchemes:正常情况下为空即可,为空代表不限制,既可以选择本地,也可以选择远程的文件。当然前提是你的平台允许选择远程文件,否则只能选择本地文件。
其实就是保存文件,例如保存某些数据到选择的本地文件中,它会返回你保存的文件名字:
QString runPath = QCoreApplication::applicationDirPath();
QString file_name = QFileDialog::getSaveFileName(this,QStringLiteral("选择路径"),runPath,"Text Files(*.txt *.png)",nullptr,QFileDialog::DontConfirmOverwrite);
static QString getSaveFileName(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
Options options = Options());
所有的参数和getOpenFileName()一样,但是注意第6个参数略有不同:
DontConfirmOverwrite这个参数有用了,如果你不写这个参数,但是选择了本来就存在的文件,那么默认是会提醒你文件是否存在的
getSaveFileUrl()和getSaveFileName()的用法几乎一样,几乎没差别。唯一的不同就是getSaveFileUrl()支持选择远程的文件,类似getOpenFileUrl()和getOpenFileName()的关系:
static QUrl getSaveFileUrl(QWidget *parent = nullptr,
const QString &caption = QString(),
const QUrl &dir = QUrl(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
Options options = Options(),
const QStringList &supportedSchemes = QStringList());
supportedSchemes:正常情况下为空即可,为空代表不限制,既可以选择本地,也可以选择远程的文件。当然前提是你的平台允许选择远程文件,否则只能选择本地文件。
getExistingDirectory()返回的是路径名字,调用这个方法是无法选择文件的,只能选择路径:
QString runPath = QCoreApplication::applicationDirPath();
QString file_name = QFileDialog::getExistingDirectory(this,QStringLiteral("选择路径"),runPath);
我们看下它的参数,很简单:
static QString getExistingDirectory(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
Options options = ShowDirsOnly);
第一个参数parent,用于指定父组件;
第二个参数caption,是对话框的标题;
第三个参数dir,是对话框显示时默认打开的目录,""不写任何参数,那么会默认打开工程的目录;
第四个参数options,默认就是ShowDirsOnly,所以你可以不写,如果你写了第四个参数,请务必把ShowDirsOnly加上!!!
否则客户会出现:可以点击文件,但是无法选择,"打开"按钮是灰色的
QString file_name = QFileDialog::getExistingDirectory(this,QStringLiteral("选择路径"),runPath,QFileDialog::DontUseNativeDialog);
getExistingDirectoryUrl()和getExistingDirectory()的用法几乎一样,几乎没差别。唯一的不同就是getExistingDirectoryUrl()支持选择远程的文件,类似getOpenFileUrl()和getOpenFileName()的关系:
static QUrl getExistingDirectoryUrl(QWidget *parent = nullptr,
const QString &caption = QString(),
const QUrl &dir = QUrl(),
Options options = ShowDirsOnly,
const QStringList &supportedSchemes = QStringList());
supportedSchemes:正常情况下为空即可,为空代表不限制,既可以选择本地,也可以选择远程的文件。当然前提是你的平台允许选择远程文件,否则只能选择本地文件。
看到getOpenFileNames()比getOpenFileName()多个‘s’,我们就自然可以想到:getOpenFileNames()是获取多个文件的名称,它的返回是QStringList,一个list:
QString runPath = QCoreApplication::applicationDirPath();
QStringList file_names = QFileDialog::getOpenFileNames(this,QStringLiteral("选择文件"),runPath,"Text Files(*.txt *.png)",nullptr);
if(!file_names.isEmpty())
{
QString list = "";
for(auto file_name : file_names)
{
list.append(file_name).append('\n');
}
ui->textEdit_getOpenFileNames->setText(list);
}
按住Ctrl可以选择多个文件,注意:最后选择的文件名在第一位
我们看下它的函数:
static QStringList getOpenFileNames(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
Options options = Options());
和getOpenFileName()相同
无需再提,就是支持远程文件。没啥好讲的,类似getOpenFileUrl()和getOpenFileName()的关系
static QList<QUrl> getOpenFileUrls(QWidget *parent = nullptr,
const QString &caption = QString(),
const QUrl &dir = QUrl(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
Options options = Options(),
const QStringList &supportedSchemes = QStringList());
返回是QUrl的一个list