新手求教:用C++开发QGIS插件(读取点坐标并显示)的完整步骤
用C++开发QGIS插件:读取点坐标并显示的完整步骤
1. 准备开发环境
- 安装带开发组件的QGIS:Windows选「QGIS Desktop with Developer Tools」,Linux安装
libqgis-dev类包,macOS通过官方安装包或Homebrew勾选开发组件 - 配置C++开发环境:安装MSVC/GCC/Clang编译器,以及CMake构建工具
- 环境变量配置:确保编译器能识别QGIS的头文件和库文件路径,Windows可手动设置
QGIS_INCLUDE_DIR、QGIS_LIB_DIR,Linux/macOS安装dev包后一般自动识别
2. 创建插件项目框架
新建项目文件夹(如PointLoaderPlugin),在其中创建CMakeLists.txt:
cmake_minimum_required(VERSION 3.16) project(PointLoaderPlugin) # 查找依赖 find_package(QGIS REQUIRED COMPONENTS core gui) find_package(Qt5 REQUIRED COMPONENTS Widgets) # 定义插件库 add_library(${PROJECT_NAME} SHARED pointloaderplugin.h pointloaderplugin.cpp pointloaderdialog.h pointloaderdialog.cpp ui_pointloaderdialog.h ) # 链接依赖库 target_link_libraries(${PROJECT_NAME} PRIVATE QGIS::core QGIS::gui Qt5::Widgets ) # 安装到QGIS插件目录 install(TARGETS ${PROJECT_NAME} DESTINATION ${QGIS_PLUGIN_DIR} )
3. 实现插件核心代码
3.1 插件主类(菜单/工具栏入口)
创建pointloaderplugin.h:
#ifndef POINTLOADERPLUGIN_H #define POINTLOADERPLUGIN_H #include <QObject> #include <qgisplugin.h> #include <QAction> class PointLoaderDialog; class PointLoaderPlugin : public QObject, public QgisPlugin { Q_OBJECT Q_INTERFACES(QgisPlugin) public: explicit PointLoaderPlugin(QgisInterface* iface); ~PointLoaderPlugin() override; void initGui() override; void unload() override; private slots: void showLoadDialog(); private: QgisInterface* mIface; QAction* mLoadAction; PointLoaderDialog* mDialog; }; #endif // POINTLOADERPLUGIN_H
创建pointloaderplugin.cpp:
#include "pointloaderplugin.h" #include "pointloaderdialog.h" PointLoaderPlugin::PointLoaderPlugin(QgisInterface* iface) : mIface(iface), mLoadAction(nullptr), mDialog(nullptr) {} PointLoaderPlugin::~PointLoaderPlugin() { unload(); } void PointLoaderPlugin::initGui() { // 创建工具栏按钮和菜单 mLoadAction = new QAction(QIcon(":/icons/point_icon.png"), "加载点坐标", this); connect(mLoadAction, &QAction::triggered, this, &PointLoaderPlugin::showLoadDialog); mIface->addToolBarIcon(mLoadAction); mIface->addPluginToMenu("&点加载工具", mLoadAction); } void PointLoaderPlugin::unload() { // 清理资源 mIface->removePluginMenu("&点加载工具", mLoadAction); mIface->removeToolBarIcon(mLoadAction); delete mLoadAction; if (mDialog) { delete mDialog; mDialog = nullptr; } } void PointLoaderPlugin::showLoadDialog() { if (!mDialog) { mDialog = new PointLoaderDialog(mIface); } mDialog->show(); }
3.2 文件选择与点加载对话框
用Qt Designer创建对话框(包含文件选择按钮、路径输入框、加载按钮),生成ui_pointloaderdialog.h。
创建pointloaderdialog.h:
#ifndef POINTLOADERDIALOG_H #define POINTLOADERDIALOG_H #include <QDialog> #include <QgisInterface> namespace Ui { class PointLoaderDialog; } class PointLoaderDialog : public QDialog { Q_OBJECT public: explicit PointLoaderDialog(QgisInterface* iface, QWidget *parent = nullptr); ~PointLoaderDialog(); private slots: void on_selectFileBtn_clicked(); void on_loadPointsBtn_clicked(); private: Ui::PointLoaderDialog *ui; QgisInterface* mIface; // 创建内存点图层 QgsVectorLayer* createPointLayer(); // 从文件读取坐标并添加到图层 bool loadPoints(const QString& filePath, QgsVectorLayer* layer); }; #endif // POINTLOADERDIALOG_H
创建pointloaderdialog.cpp:
#include "pointloaderdialog.h" #include "ui_pointloaderdialog.h" #include <QFileDialog> #include <QFile> #include <QTextStream> #include <QMessageBox> #include <QgsFeature> #include <QgsGeometry> #include <QgsPointXY> #include <QgsProject> PointLoaderDialog::PointLoaderDialog(QgisInterface* iface, QWidget *parent) : QDialog(parent), ui(new Ui::PointLoaderDialog), mIface(iface) { ui->setupUi(this); } PointLoaderDialog::~PointLoaderDialog() { delete ui; } void PointLoaderDialog::on_selectFileBtn_clicked() { QString filePath = QFileDialog::getOpenFileName(this, "选择坐标文件", "", "文本文件 (*.txt);;所有文件 (*.*)"); if (!filePath.isEmpty()) { ui->filePathEdit->setText(filePath); } } QgsVectorLayer* PointLoaderDialog::createPointLayer() { // 创建WGS84坐标系的内存点图层 QString layerName = "导入的点"; QgsVectorLayer* layer = new QgsVectorLayer("Point?crs=EPSG:4326", layerName, "memory"); return layer->isValid() ? layer : nullptr; } bool PointLoaderDialog::loadPoints(const QString& filePath, QgsVectorLayer* layer) { QFile file(filePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::warning(this, "错误", "无法打开文件"); return false; } QTextStream in(&file); QgsFeature feature(layer->fields()); QList<QgsFeature> featureList; while (!in.atEnd()) { QString line = in.readLine().trimmed(); if (line.isEmpty()) continue; // 解析逗号分隔的经纬度(格式:经度,纬度) QStringList coords = line.split(","); if (coords.size() != 2) continue; bool lonOk, latOk; double lon = coords[0].toDouble(&lonOk); double lat = coords[1].toDouble(&latOk); if (!lonOk || !latOk) continue; feature.setGeometry(QgsGeometry::fromPointXY(QgsPointXY(lon, lat))); featureList.append(feature); } // 添加要素到图层 if (!layer->dataProvider()->addFeatures(featureList)) { QMessageBox::warning(this, "错误", "添加点失败"); return false; } layer->updateExtents(); file.close(); return true; } void PointLoaderDialog::on_loadPointsBtn_clicked() { QString filePath = ui->filePathEdit->text(); if (filePath.isEmpty()) { QMessageBox::warning(this, "提示", "请先选择坐标文件"); return; } QgsVectorLayer* layer = createPointLayer(); if (!layer) { QMessageBox::warning(this, "错误", "创建图层失败"); return; } if (loadPoints(filePath, layer)) { // 将图层添加到项目并刷新画布 QgsProject::instance()->addMapLayer(layer); mIface->mapCanvas()->refresh(); this->close(); } }
4. 编译与安装插件
- 创建
build目录,进入后执行编译命令:# Linux/macOS cmake .. -DCMAKE_BUILD_TYPE=Release make sudo make install # Windows(MSVC环境) cmake .. -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=Release cmake --build . --config Release --target INSTALL - 手动安装:将编译生成的库文件(
.so/.dll/.dylib)复制到QGIS插件目录:- Linux:
~/.local/share/QGIS/QGIS3/profiles/default/plugins/ - Windows:
C:\Users\<用户名>\AppData\Roaming\QGIS\QGIS3\profiles\default\plugins\ - macOS:
~/Library/Application Support/QGIS/QGIS3/profiles/default/plugins/
- Linux:
5. 测试插件
- 启动QGIS,在「插件」菜单找到「点加载工具」并启用
- 点击工具栏的「加载点坐标」按钮,选择符合格式的坐标文件(每行
经度,纬度),加载后即可在画布看到点要素
关键注意事项
- 坐标格式适配:如果文件是空格/制表符分隔或带表头,需修改
loadPoints里的解析逻辑 - 坐标系调整:若坐标使用其他坐标系,修改
createPointLayer中的EPSG代码即可 - 错误处理:示例代码添加了基础提示,实际开发可根据需求扩展异常处理逻辑
内容的提问来源于stack exchange,提问作者wangxin
相关产品推荐
相关产品推荐

