一、環境
開發環境為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、設置宏定義【編譯會出現未定義標識符“M_PI”】
右鍵項目,C/C++,預處理器,預處理器定義,添加_USE_MATH_DEFINES

7、編譯程序生成exe【必須是64位和release,64位是因為要與QGis位數一致】
8、將相關動態庫放到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文件,並將文件存到內存里,然后依次繪制到畫布中。

