一、环境
开发环境为VS2019+Qt14,编译器为MSVC【MingW在windows下的动态库为.a文件,但是现成的QGIS动态库是dll的,所以选择MSVC,以免麻烦】
配置vs+qt环境,参考:https://www.cnblogs.com/judes/p/8992231.html
二、安装QGIS相关【用于获取桌面版和二次开发依赖包,也可直接下载现成的,见此节末尾】
1、安装桌面版【只是使用Qt开发的一个工具,可以用来玩玩,只要这个工具有的功能,理论上都能通过二次开发QGIS库开发出来】,参考:https://www.cnblogs.com/judes/p/15143756.html
大概熟悉一下,如使用OSM【OpenStreetMap,开源,很多webgis和接口gis都用这个】图层,在线高德图层、谷歌图层、3D、2维....
2、安装好桌面版之后,需要下载QGIS运行库【后续二次开发所依赖的库】,打开配置工具
3、按照下图依次下一步
这里需要注意下,我最开始按照其他博客选择最后一个,但是下载失败,一直提示license有问题,选择第二个就ok了
然后等待下载,会比较慢,我在家里是每秒几百k,大概等了半小时
3、下载完成
后面二次开发的依赖就在这里面
注意:
如果不想自己下载安装这么多东西,也可以直接网上找现成的编译好了的依赖库,我就是这样做的【下文也按照此路径进行配置】,下载来是这样的:
跟上面差不多。此外也可以网上找如何对QGIS进行源码编译的方法,是基于CMake的,如果是跨环境估计就得用这方法了。
三、下载地图瓦片数据
QGIS的瓦片数据类型是shp的,可在此网站下载:http://download.geofabrik.de/,下载下来里面有很多,如建筑、学校、工厂等等,这里做实验随便留一个备用
四、新建工程及环境配置
1、打开vs,新建Qt gui widget工程,源文件如下:
2、右键项目,为项目添加svg和xml的Qt模块
为啥要加这模块呢,是因为QGis源码里会用到。
3、设置附加包目录【头文件目录】
D:\soft\OSGeo4W64\include
D:\soft\OSGeo4W64\apps\qgis-ltr\include
4、设置附加库目录【lib文件的目录】
D:\soft\OSGeo4W64\apps\qgis-ltr\lib
5、设置附加依赖项【依赖的dll动态库】
qgis_core.lib
qgis_app.lib
qgis_gui.lib
6、编译程序生成exe【必须是64位和release,64位是因为要与QGis位数一致】
7、将相关动态库放到exe同一路径,以免运行失败
①、路径1的dll
D:\soft\OSGeo4W64\apps\qgis-ltr\bin
D:\soft\OSGeo4W64\bin
②、路径2的dll
D:\soft\OSGeo4W64\apps\Qt5\bin
③、路径3的文件夹
D:\soft\OSGeo4W64\apps\Qt5\plugins下的整个platforms文件夹
最终可执行文件夹是这样的:
注意都要复制,不然后面代码写了也不能运行,会报无dll错误和Qt platforms错误。至此二次开发环境就ok了。
五、代码编写
1、qtwidgetsapplication.h
#pragma once #include <QtWidgets/QMainWindow> #include "ui_qtwidgetsapplication.h" #include <qmenu.h> #include <qaction.h> #include <qgsmapcanvas.h> class QtWidgetsApplication : public QMainWindow { Q_OBJECT public: QtWidgetsApplication(QWidget *parent = Q_NULLPTR); private: Ui::QtWidgetsApplicationClass ui; QMenu* fileMenu; QAction* openFileAction; QgsMapCanvas* mapCanvas; QList<QgsMapLayer*> layers; public slots: void on_openFileAction_triggered(); // public: void addVectorLayer(); };
2、qtwidgetsapplication.cpp
#include "qtwidgetsapplication.h" #include <qmenubar.h> #include <qmessagebox.h> #include <qfiledialog.h> #include <qgsvectorlayer.h> QtWidgetsApplication::QtWidgetsApplication(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); this->resize(600, 400); // create the menus and then add the actions to them. fileMenu = this->menuBar()->addMenu("File"); openFileAction = new QAction("Open", this); this->connect(openFileAction, SIGNAL(triggered(bool)), this, SLOT(on_openFileAction_triggered())); fileMenu->addAction(openFileAction); // initialize the map canvas mapCanvas = new QgsMapCanvas(); this->setCentralWidget(mapCanvas); mapCanvas->setCanvasColor(QColor(255, 255, 255)); mapCanvas->setVisible(true); mapCanvas->enableAntiAliasing(true); } void QtWidgetsApplication::on_openFileAction_triggered() { addVectorLayer(); } void QtWidgetsApplication::addVectorLayer() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open shape file"), "", "*.shp"); //QString fileName = QFileDialog::getOpenFileName(this, tr("Open shape file"), "", "*"); QStringList temp = fileName.split(‘/‘); QString basename = temp.at(temp.size() - 1); QgsVectorLayer* vecLayer = new QgsVectorLayer(fileName, basename, "ogr"); if (!vecLayer->isValid()) { QMessageBox::critical(this, "error", QString("layer is invalid: \n") + fileName); return; } mapCanvas->setExtent(vecLayer->extent()); layers.append(vecLayer); mapCanvas->setLayers(layers); mapCanvas->refresh(); }
3、main.cpp
#include "qtwidgetsapplication.h" #include <QtWidgets/QApplication> #include <qgsapplication.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); QtWidgetsApplication w; w.show(); return a.exec(); }
原理就是在mainwindow里,增加一个点击action,点击后打开shp文件,并将文件存到内存里,然后依次绘制到画布中。