安装环境搭建
QGIS的二次开发支持Windows和Linux下进行,这里分别介绍一下环境搭建。
Windows下环境搭建(待详细介绍)
MSVC 2022 安装
官网下载VS2022,安装时选择C++的开发环境。
Qt安装
在线安装Qt即可,最新的QGIS 3.40 版本下载的Qt库是Qt6,需要安装Qt6的开发环境。
QGIS dev开发环境安装
Windows下环境搭建比较简单,直接下载QGIS的在线安装包OSGeo4W进行安装-dev版本的即可。
Ubuntu22下环境搭建
(可选)WSl安装Ubuntu 22
我是直接在Windows上安装的WSL2,直接在Windows上安装Ubuntu22.04即可。
wsl --install Ubuntu-22.04
安装系统依赖
参考:QGIS官方安装说明
sudo apt-get update
sudo apt-get install bison build-essential ca-certificates ccache cmake cmake-curses-gui dh-python expect flex flip gdal-bin git graphviz grass-dev libdraco-dev libexiv2-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libpdal-dev libpq-dev libproj-dev libprotobuf-dev libqca-qt5-2-dev libqca-qt5-2-plugins libqscintilla2-qt5-dev libqt5opengl5-dev libqt5serialport5-dev libqt5sql5-sqlite libqt5svg5-dev libqt5webkit5-dev libqt5xmlpatterns5-dev libqwt-qt5-dev libspatialindex-dev libspatialite-dev libsqlite3-dev libsqlite3-mod-spatialite libyaml-tiny-perl libzip-dev libzstd-dev lighttpd locales ninja-build nlohmann-json3-dev ocl-icd-opencl-dev opencl-headers pandoc pdal pkgconf poppler-utils protobuf-compiler pyqt5-dev pyqt5-dev-tools pyqt5.qsci-dev python3-all-dev python3-autopep8 python3-dev python3-gdal python3-jinja2 python3-lxml python3-mock python3-nose2 python3-owslib python3-packaging python3-plotly python3-psycopg2 python3-pygments python3-pyproj python3-pyqt5 python3-pyqt5.qsci python3-pyqt5.qtmultimedia python3-pyqt5.qtpositioning python3-pyqt5.qtserialport python3-pyqt5.qtsql python3-pyqt5.qtsvg python3-pyqt5.qtwebkit python3-pyqtbuild python3-sip python3-termcolor python3-yaml qt3d-assimpsceneimport-plugin qt3d-defaultgeometryloader-plugin qt3d-gltfsceneio-plugin qt3d-scene2d-plugin qt3d5-dev qtbase5-dev qtbase5-private-dev qtkeychain-qt5-dev qtmultimedia5-dev qtpositioning5-dev qttools5-dev qttools5-dev-tools sip-tools spawn-fcgi xauth xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable xvfb
设置 ccache(可选,但推荐)
您还应该设置 ccache 以加快编译时间:
cd /usr/local/bin
sudo ln -s /usr/bin/ccache gcc
sudo ln -s /usr/bin/ccache g++
下载QGIS源码
mkdir ~/dev
cd ~/dev
git clone https://github.com/qgis/QGIS.git
cd QGIS
# 切换到3.40分支
git checkout release-3_40
启动编译
这里是直接安装到系统目录下,需要sudo ninja install权限。 如果需要安装到指定位置,cmake命令需要添加参数:-D CMAKE_INSTALL_PREFIX=${HOME}/apps
mkdir ~/apps
mkdir build
cd build
cmake -G Ninja -D WITH_3D=false ..
# 如果需要安装到用户目录下
# cmake -G Ninja -D WITH_3D=false -D CMAKE_INSTALL_PREFIX=${HOME}/apps ..
构建
ninja
sudo ninja install # 如果是安装到用户目录下,不需要带sudo
创建Qt项目
项目结构
MapView/
├── CMakeLists.txt
├── main.cpp
├── mainwindow.cpp
├── mainwindow.h
├── mainwindow.ui
├── resources.qrc
CMakeLists.txt 配置
可参考下面的cmake配置文件,如果QGIS是安装到用户目录下,需要指定QGIS的include和lib目录
cmake_minimum_required(VERSION 3.14)
project(MapView VERSION 0.1 LANGUAGES CXX)
# Set build type to Release
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Xml PrintSupport)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Xml PrintSupport)
# QGIS configuration - use system installation
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
pkg_check_modules(QGIS QUIET qgis)
endif()
# Find QGIS libraries from system installation
find_library(QGIS_CORE_LIBRARY NAMES qgis_core)
find_library(QGIS_GUI_LIBRARY NAMES qgis_gui)
find_library(QGIS_APP_LIBRARY NAMES qgis_app)
find_library(QGIS_NATIVE_LIBRARY NAMES qgis_native)
find_library(QGIS_ANALYSIS_LIBRARY NAMES qgis_analysis)
# Check if QGIS is available
if(QGIS_CORE_LIBRARY)
message(STATUS "QGIS libraries found in system")
set(QGIS_FOUND TRUE)
# Try to find QGIS include directory
find_path(QGIS_INCLUDE_DIR qgis.h
PATHS /usr/include/qgis /usr/local/include/qgis
PATH_SUFFIXES qgis
)
if(QGIS_INCLUDE_DIR)
message(STATUS "QGIS include directory: ${QGIS_INCLUDE_DIR}")
else()
message(WARNING "QGIS include directory not found")
endif()
else()
message(WARNING "QGIS libraries not found in system - building without QGIS support")
set(QGIS_FOUND FALSE)
endif()
# Automatically collect all source files
file(GLOB_RECURSE PROJECT_SOURCES
"*.cpp"
"*.h"
"*.ui"
"*.qrc"
)
# Filter out build directory if it exists
list(FILTER PROJECT_SOURCES EXCLUDE REGEX "${CMAKE_BINARY_DIR}/.*")
# Print found sources for debugging
message(STATUS "Found source files: ${PROJECT_SOURCES}")
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(MapView
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
else()
add_executable(MapView
${PROJECT_SOURCES}
)
endif()
# Add QGIS support if available
if(QGIS_FOUND)
if(QGIS_INCLUDE_DIR)
target_include_directories(MapView PRIVATE ${QGIS_INCLUDE_DIR})
endif()
target_compile_definitions(MapView PRIVATE
_USE_MATH_DEFINES
QGIS_ENABLED
)
else()
target_compile_definitions(MapView PRIVATE _USE_MATH_DEFINES)
endif()
# Link Qt libraries
target_link_libraries(MapView PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Xml Qt${QT_VERSION_MAJOR}::PrintSupport)
# Link QGIS libraries if available
if(QGIS_FOUND)
target_link_libraries(MapView PRIVATE
${QGIS_CORE_LIBRARY}
${QGIS_GUI_LIBRARY}
${QGIS_APP_LIBRARY}
${QGIS_NATIVE_LIBRARY}
${QGIS_ANALYSIS_LIBRARY}
)
# Set RPATH to find QGIS libraries at runtime (system paths)
set_target_properties(MapView PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH_USE_LINK_PATH TRUE
)
endif()
if(${QT_VERSION} VERSION_LESS 6.1.0)
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.MapView)
endif()
set_target_properties(MapView PROPERTIES
${BUNDLE_ID_OPTION}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(MapView)
endif()
主要代码片段
main.cpp
#include "mainwindow.h"
#include "qgsapplication.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QgsApplication a(argc, argv, true);
a.init();
a.initQgis();
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "mapcanvas/mapcanvas.h"
#include "qgsmaptoolpan.h"
#include <qnamespace.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
setWindowTitle(QStringLiteral("软件标题"));
// 自定义地图类,实现自己的地图功能
MapCanvas *mapcanvas = new MapCanvas(this);
// 地图画布设置为黑色
mapcanvas->setCanvasColor(Qt::black);
// 这一步是把MapCanvas放到窗口布局的下面,这样可以实现Qt的控件叠加显示在地图上面
ui->gridLayout->addWidget(mapcanvas, 0, 0, 1, 1);
// mapcanvas->lower();
// 设置地图工具,默认自带拖拽移动和缩放,可创建新的类实现自己想要的操作逻辑
QgsMapToolPan *maptool = new QgsMapToolPan(mapcanvas);
mapcanvas->setMapTool(maptool);
}
MainWindow::~MainWindow() { delete ui; }
mapcanvas.cpp
#include "mapcanvas.h"
QgsRasterLayer *MapCanvas::getInitRasterLayer(const QString &url,
const QString &name) {
QgsRasterLayer *raster = new QgsRasterLayer(url, name);
// raster->setCrs(QgsCoordinateReferenceSystem::fromEpsgId(3857));
this->setExtent(raster->extent());
auto layers = this->layers();
layers.append(raster);
this->setLayers(layers);
this->zoomToFullExtent();
this->refresh();
return raster;
}
MapCanvas::~MapCanvas() {
if (_qgsproject) {
_qgsproject->removeAllMapLayers();
}
}
MapCanvas::MapCanvas(QWidget *parent) : QgsMapCanvas(parent) {
_qgsproject = QgsProject::instance();
// 这是一个我自己写的生成xml文件的类,用于生成qgis需要的xml文件
XmlGenerator xmlGen;
xmlGen.generateXmlFiles();
// 这里是两个图层,图层可以叠加显示,也可以自己写逻辑,切换显示
QString street_file = xmlGen.GetStreetXmlFile();
QString satellite_file = xmlGen.GetSatelliteXmlFile();
// _street_layer = getInitRasterLayer(street_file, "street");
_satellite_layer = getInitRasterLayer(satellite_file, "satellite");
// _qgsproject->addMapLayer(_street_layer);
// 把图层添加到qgsproject中
_qgsproject->addMapLayer(_satellite_layer);
setProject(_qgsproject);
}