天天看点

QFileDialog静态接口调用系统资源管理器崩溃问题问题现象解决方法

问题现象

  • 调用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;
}
           

继续阅读