利用QGIS 3.26.2编写的GIS程序,在本人开发机器能正常运行,但是放到其它机器,起来一会儿后闪退,程序退出。
本人用到的开发环境说明如下:
QGIS 3.26.2
Qt 5.14.1
Visual Studio 2019
在执行如下代码:
m_pMapCanvas = new QgsMapCanvas(this);
会崩溃,从而导致程序退出。崩溃原因为:构造QgsMapCanvas 对象时,会调用QGIS底层的src\core\qgsapplication.cpp中的如下函数:
图1
因找不到主程序同级目录resources目录下的srs6.db导致copy函数失败,从而调用qFatal使程序终止退出。
找到GIS工程的main.cpp,在main函数的
QgsApplication a(argc, argv, true);
和
QgsApplication::initQgis(); //初始化QGIS应用
代码之间,加入如下writePathToQGisBulidFile函数,该函数的定义如下:
// QgsApplication底层要用到这些路径或文件,如果不创建,程序功能会不正常
void writePathToQGisBulidFile()
{auto appDir = qApp->applicationDirPath();auto qsQgisBuildFilePath = appDir + "/../qgisbuildpath.txt";auto appResourceDir = appDir + QDir::separator() + "resources";// 创建resources目录QDir gisAppResourceDir;gisAppResourceDir.mkpath(appResourceDir);// 获取resources目录下的srs6.db文件的绝对路径auto qsSrs6DB_FilePath = appResourceDir + QDir::separator() + "srs6.db";// 如果srs6.db文件不存在,就终止程序,这比到底层终止程序更容易排查问题。if (!QFile(qsSrs6DB_FilePath).exists()){qFatal("srs6.db must be need! please use sqlite3.exe create this file!!!");}/* 将appDir、parenPath写入到GIS主程序父目录下的qgisbuildpath.txt文件*/QFile data(qsQgisBuildFilePath);if (data.open(QFile::WriteOnly | QFile::Truncate)){QFileInfo fileInfo(qsQgisBuildFilePath);auto dir = fileInfo.absoluteDir();auto parenPath = dir.path();QTextStream out(&data);out << appDir << "\r\n " << parenPath;data.close();}
}
说明:函数最后将appDir、parenPath按行写入到GIS主程序父目录下的qgisbuildpath.txt文件。这是因为,在QGIS的QgsApplication类的resolvePkgPath函数对*sBuildSourcePath()、*sBuildOutputPath()进行赋值,所赋的值就是从qgisbuildpath.txt文件按行读取的。
QString QgsApplication::resolvePkgPath()
{..... // 其它代码略,请自行查看代码for ( const QString &path : paths ){f.setFileName( prefix + path + "/qgisbuildpath.txt" );if ( f.exists() )break;}if ( f.exists() && f.open( QIODevice::ReadOnly ) ){ABISYM( mRunningFromBuildDir ) = true;*sBuildSourcePath() = f.readLine().trimmed();*sBuildOutputPath() = f.readLine().trimmed();..... // 其它代码略,请自行查看代码}}..... // 其它代码略,请自行查看代码
如果不写入appDir到qgisbuildpath.txt文件的第1行,则导致*sBuildSourcePath()为空,从而导致图1代码因找不到srs6.db文件导致拷贝失败,引起程序退出。
如果不写入parenPath到qgisbuildpath.txt文件的第2行,则*sBuildOutputPath()为空,此时自己编写的主程序,如果想输出到自己设定目录而不是默认生成的目录下会有问题。另外,当断点调试某些dll时,不能进入源码。具体参见《QGIS二次开发:将主程序生成到自定义目录遇到的问题解决汇总》。
从sqlite3官网SQLite Download Page下载sqlite3.exe(或如果你安装了QGIS的官方应用程序,在则安装目录下的bin下找到sqlite3.exe),按win和R组合键,调出运行对话框,输入cmd,打开Windows下的cmd窗口,输入:
C:\Users\dansh>"C:\Program Files\QGIS 3.26.2\bin\sqlite3.exe"
请根据你的sqlite3.exe,更改实际路径。按回车,进入到sqlite3的命令行界面,输入如下命令:
sqlite> .open d:\\srs6.db
将生成的srs6.db拷贝到上述resources目录。输入.quit,退出sqlite3的命令行界面。