问题现象
- 调用QFileDialog的静态函数(比如getFileName)在客户环境下会有随机崩溃现象,无法捕获异常,也没有任何提示信息。
- 根据网页资料 https://www.cnblogs.com/zi-xing/p/6217172.html 推测,怀疑是静态函数调用的系统资源文件管理器跟某些软件冲突导致。解决方法就是使用QT封装的文件对话框代替系统资源文件管理器。
解决方法
简单写法
- 静态函数调用的时候设置参数:Options options( QFileDialog::DontUseNativeDialog ),意思就是不使用系统资源文件管理器。这样代码代码改动最小,但是有2个缺点:
- 默认样式带问号,不美观
- 选择保存路径的时候,不自动添加文件后缀,使用不方便
复杂写法
- 自定义文件对话框类FileDialogEx,继承QFileDialog。
- 构造函数中设置对话框属性样式,取消问号
- 封装对应的静态接口
对话框样式属性设置
FileDialogEx::FileDialogEx(QWidget *parent /*= nullptr*/,
const QString &caption /*= QString()*/,
const QString &directory /*= QString()*/,
const QString &filter /*= QString()*/) :QFileDialog(parent,caption,directory,filter)
{
Qt::WindowFlags flags = Qt::Dialog | Qt::WindowCloseButtonHint;
this->setWindowFlags(flags);
this->setModal(true);
this->setOption(QFileDialog::DontUseNativeDialog); ///< 不是用本地对话框
}
封装选择保存路径接口,自动添加文件后缀
QString FileDialogEx::GetSaveFileNameEx()
{
QString strSaveFileName;
this->setAcceptMode(AcceptSave);
if (this->exec() == QDialog::Accepted)
{
strSaveFileName = selectedFiles().value(0);
QString strTempSelectedFilter = selectedNameFilter();
int nStart = strTempSelectedFilter.indexOf("(");
int nEnd = strTempSelectedFilter.indexOf(")");
int nLength = nEnd - nStart -2;
QString strSelectedFilter = strTempSelectedFilter.mid(nStart+2, nLength);
if (!strSaveFileName.endsWith(strSelectedFilter))
{
strSaveFileName.append(strSelectedFilter);
}
}
return strSaveFileName;
}
封装选择路径接口
QString FileDialogEx::GetExistingDirectoryEx()
{
QString strExistingDir;
this->setFileMode(QFileDialog::DirectoryOnly);
if (this->exec() == QDialog::Accepted)
{
strExistingDir = selectedFiles().value(0);
}
return strExistingDir;
}
封装选择单个文件接口
QString FileDialogEx::GetOpenFileNameEx()
{
QString strOpenFileName;
this->setAcceptMode(AcceptOpen);
if (this->exec() == QDialog::Accepted)
{
strOpenFileName = selectedFiles().value(0);
}
return strOpenFileName;
}
封装选择多个文件接口
QStringList FileDialogEx::GetOpenFileNamesEx()
{
QStringList strOpenFileNames;
this->setAcceptMode(AcceptOpen);
this->setFileMode(QFileDialog::ExistingFiles);
if (this->exec() == QDialog::Accepted)
{
strOpenFileNames = selectedFiles();
}
return strOpenFileNames;
}