天天看點

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;
}
           

繼續閱讀