QGIS二次开发:构造QgsMapCanvas类对象导致闪退问题解决
创始人
2025-05-30 13:04:40

1.现象描述

利用QGIS 3.26.2编写的GIS程序,在本人开发机器能正常运行,但是放到其它机器,起来一会儿后闪退,程序退出。

2.开发环境说明

本人用到的开发环境说明如下:

  • QGIS 3.26.2

  • Qt 5.14.1

  • Visual Studio 2019

3.问题原因

在执行如下代码:

  m_pMapCanvas = new QgsMapCanvas(this);

会崩溃,从而导致程序退出。崩溃原因为:构造QgsMapCanvas 对象时,会调用QGIS底层的src\core\qgsapplication.cpp中的如下函数:

图1

因找不到主程序同级目录resources目录下的srs6.db导致copy函数失败,从而调用qFatal使程序终止退出。

4.解决方法

找到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的命令行界面。

相关内容

热门资讯

荼蘼什么意思 岁月缱绻葳蕤生香... 感谢作者【辰夕】的原创独家授权分享编辑整理:【多肉植物百科】百科君坐标:云南 曲靖春而至,季节流转,...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...