简介本资源是QGIS官方示例代码合集面向地理信息系统初学者、二次开发人员及开源GIS工具实践者旨在解决国内QGIS编程学习资料匮乏、示例零散、入门门槛高的实际问题。压缩包共220个文件涵盖C源码20个.cpp、11个.h、构建脚本15个CMakeLists.txt、3个Makefile、界面资源6个.ui、6个.qrc、矢量与栅格测试数据shp/dbf/prj/shx/tif等以及配套文档与图片21个.png、5个.jpg、4个.html整体仅1.1MB轻量易用。已有355人学习下载说明其在QGIS插件开发、地图渲染、矢量属性访问、自定义地图工具编写等核心场景中具备较强参考价值。目录结构按功能模块组织从Hello World风格的样式设置到橡胶带交互、栅格加载、标签配置等进阶操作完整覆盖QGIS C API典型应用路径可直接编译运行并作为二次开发的可靠起点。 我这几年前前后后带过不少人入门QGIS二次开发每次被问到“PyQGIS从哪下手”我的答案从来没变过先啃官方例子。不是让你把几千行源码逐行读完而是要知道官方例子的组织方式、核心调用模式然后照着改、照着跑、照着拆。这个项目标题叫“qgis官方例子学习代码”说白了就是一条被验证过无数次的入门路径。今天我把这条路径完整拆给你看包括官方例子藏在哪、哪些例子性价比最高、怎么把示例代码改成自己的工具以及我自己踩过的那些坑。1. 整体设计为什么“啃官方例子”是最快的入门路径1.1 官方例子到底藏在哪里很多人学PyQGIS的第一个障碍不是语法而是“找不到代码”。QGIS的官方例子其实分布在三个地方我按优先级给你排好第一优先级QGIS安装目录里的Python插件源码。以Linux下通过apt安装的QGIS为例路径通常在/usr/share/qgis/python/plugins/Windows下一般在C:\Program Files\QGIS 3.xx\apps\qgis\python\plugins\。这里面是Processing工具箱的全部内置算法每个算法都是一个独立的Python文件代码量从几十行到几百行不等。比如processing/algs/qgis/这个目录你会看到buffer.py、centroids.py、intersection.py这些“教科书级”的例子它们用的全是公开API没有任何私有接口。第二优先级PyQGIS Cookbook开发者 cookbook。官方文档站在docs.qgis.org上有中文版本里面有大量的“加载图层”“遍历要素”“修改几何”的独立代码片段。这些片段虽然短但每一段都可以直接跑是理解API用法最干净的素材。第三优先级QGIS源码仓库。GitHub上的qgis/QGIS仓库重点看python/目录尤其python/console/和python/pyplugin_installer/这两个目录它们是用PyQGIS写完整功能应用的活教材。1.2 一条被验证过的学习路线关于“QGIS官方例子学习代码”我建议你按这个顺序来而不是今天看一个buffer、明天看一个centroids毫无章法地乱刷阶段一跑通文档片段1周。把Cookbook里的图层加载、要素遍历、几何修改这些代码全部复制到QGIS内置Python控制台里跑一遍。这个阶段的目标不是写代码而是建立“调用直觉”——告诉大脑QGIS里加载图层不是open()而是QgsVectorLayer()加QgsProject.instance().addMapLayer()。阶段二拆解Processing算法2~4周。选10个常用的官方算法逐个分析输入参数定义、处理流程、输出注册。这是我觉得收益最大的一步Processing算法有统一的initAlgorithm()和processAlgorithm()结构你拆完10个以后写插件或者独立脚本的骨架感就出来了。阶段三改写并造自己的轮子持续。把官方例子改造成自己的工具比如官方有缓冲区算法你就改成“根据属性字段动态设置缓冲区距离”官方有矢量裁剪你就改成“批量裁切多个图层”。改的过程才是真正“学到”的过程。1.3 官方例子能让你学到什么我自己的体会是官方例子带来的最有价值的信息不是某个API怎么用而是QGIS官方推荐的代码组织和命名方式。举个例子官方插件里处理图层最常用的信号是layer.geometryChanged和layer.attributeChanged在官方例子中出现的频率极高。你会发现它们处理“编辑后联动”这件事的思路是先layer.startEditing()然后捕获信号最后layer.commitChanges()。这套三步走是官方反复使用的模式你在自己的代码里用了就少走很多弯路。另外官方例子还教会我“如何优雅地处理CRS坐标系参考”。新手最容易犯的错就是直接crs QgsCoordinateReferenceSystem(4326)硬编码但官方例子里统一用QgsCoordinateReferenceSystem.fromEpsgId(4326)并且每次做几何运算前都会检查sourceCrs.isValid()这给我省了无数麻烦。2. 核心细节解析必须吃透的5个API模式2.1 项目、图层、要素三层对象模型学习QGIS官方代码最先要搞清楚的是对象模型。QGIS里的数据组织是三层结构QgsProject管理整个工程比如添加/移除图层、保存/加载工程文件。官方例子里常用QgsProject.instance()获取全局单例。QgsMapLayer及其子类代表一个图层可以是QgsVectorLayer或QgsRasterLayer。QgsFeature图层里的一个要素包含几何QgsGeometry和属性QgsAttributes。官方例子里最常见的起始代码是这样的from qgis.core import QgsVectorLayer, QgsProject layer QgsVectorLayer(/path/to/shapefile.shp, my_layer, ogr) QgsProject.instance().addMapLayer(layer)第二行QgsVectorLayer三个参数分别是数据源路径、图层显示名、数据提供器类型。这里的ogr是QGIS里读写矢量数据的统一接口它可以读shapefile、GeoJSON、GeoPackage甚至DWG经过转换后。你如果跑过官方例子会经常看到providerType参数它不只是ogr还可能是memory临时图层、postgresPostGIS数据库等。想彻底理解建议你把同一个例子分别改成这三种类型跑一遍就明白参数的意义了。2.2 信号槽机制地图这件事必须靠监听GIS应用和普通CRUD应用最大的区别是地图状态会随着用户操作平移、缩放、选中、编辑不断变化。官方例子几乎都是靠信号槽来响应变化的而不是靠轮询。比如要实现“图层要素被编辑后自动更新统计信息”官方例子的写法是def on_feature_changed(feature): print(Feature changed:, feature.id(), feature.attribute(0)) layer.featureChanged.connect(on_feature_changed) layer.startEditing() # 模拟修改一个要素 feat next(layer.getFeatures()) layer.changeAttributeValue(feat.id(), 0, 新的属性值) layer.commitChanges()这里是featureChanged信号在起作用。注意顺序先连接信号再startEditing()最后commitChanges()。如果顺序反了信号可能捕获不到任何变化。实际项目里还有一个官方例子反复使用的模式是用QgsMapToolIdentify做要素拾取然后通过activeLayer().featureSelected信号把要素传给业务逻辑。如果你想做那种“点击地图某条路显示它的属性信息”的功能一定先去官方插件里搜这个信号。2.3 几何操作API的顺序感很重要官方代码里几何操作都是直接操作QgsGeometry对象。你要记住一个规律QgsGeometry 是不可变的数据载体每次操作都返回新的几何体。比如“根据拐点坐标创建多边形”的热搜词官方写法是from qgis.core import QgsGeometry, QgsPointXY points [ QgsPointXY(100.0, 0.0), QgsPointXY(101.0, 0.0), QgsPointXY(101.0, 1.0), QgsPointXY(100.0, 1.0), ] geom QgsGeometry.fromPolygonXY([[points]]) print(geom.asWkt()) # 输出: POLYGON((100 0, 101 0, 101 1, 100 1, 100 0))这里最容易被忽略的是[[points]]的双层列表结构。因为多边形可能有多个环外环加内环所以fromPolygonXY接收的是“环的列表”每个环又是一个点列表。如果坐标是经纬度记得要先设置好图层的CRS否则面积计算和投影会出错。2.4 图层编辑事务式的startEditing和commitChanges在QGIS官方例子中对矢量图层的修改永远是三步曲startEditing()开始编辑修改操作addFeature、changeAttributeValue、deleteFeature然后commitChanges()提交。如果你连续操作多个要素可以这样写layer.startEditing() for i in range(10): feat QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(i, i))) layer.addFeature(feat) layer.commitChanges()注意一旦commitChanges()失败比如数据源只读、字段约束冲突程序不会自动回滚。官方例子一般会做这个检查if not layer.commitChanges(): print(Commit failed:, layer.commitErrors()) layer.rollBack() # 手动回滚这个rollBack()是我看了很多官方算法之后才注意到的细节不写你会踩大坑。2.5 外部独立脚本的初始化模板我见过太多人把代码写在QGIS插件里能跑独立一跑就报错。原因是在独立Python脚本里使用PyQGIS必须先初始化QGIS应用环境。一个可用的模板是import sys from qgis.core import QgsApplication QgsApplication.setPrefixPath(/usr/bin, True) # 这里要写你QGIS的安装路径 qgs QgsApplication([], False) qgs.initQgis() # 你的业务代码写在这里 qgs.exitQgis()注意Windows下前缀路径一般是C:/Program Files/QGIS 3.xx/apps/qgis。如果没有设置setPrefixPathQgsApplication找不到Python插件和proj库会报各种诡异的错误。这个模板在官方文档里没有明说但在官方插件的测试代码里很常见。3. 实操复现从官方示例到你自己的自动化脚本3.1 用QGIS内置控制台体验“加载图层并遍历要素”我强烈建议你一开始不要写独立脚本而是打开QGIS桌面端点菜单“插件 → Python控制台”在控制台里直接写代码所见即所得还能看print()输出。先跑这个最简单的官方示例# 创建一个空的临时图层 layer QgsVectorLayer(Point?crsEPSG:4326, temp_points, memory) QgsProject.instance().addMapLayer(layer) # 添加三个点要素 layer.startEditing() for i in range(3): feat QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10 i, 20 i))) layer.addFeature(feat) layer.commitChanges() # 遍历要素 for feature in layer.getFeatures(): print(feature.id(), feature.geometry().asWkt())先解释第一行Point?crsEPSG:4326是用URI方式定义一个内存点图层。这个字符串语法可以在官方示例里反复看到它属于memory数据提供器的专用格式后面的crs参数指定坐标系。跑完之后你应该能在图层列表看到新图层控制台输出三个要素的信息。如果你连这一步都跑通恭喜你PyQGIS的“Hello World”已经完成了。3.2 复现官方示例加载本地CSV点位图层并编辑热搜词里有“我导入的csv点位图层qgis,怎么编辑”这确实是高频需求。在官方例子中CSV文件可以直接通过QgsVectorLayer加载但与传统矢量文件不同CSV没有几何定义需要指定x、y字段。假设你的CSV有lon和lat两列代码是这样uri file:///home/user/points.csv?delimiter,xFieldlonyFieldlatcrsEPSG:4326 layer QgsVectorLayer(uri, csv_points, delimitedtext) if not layer.isValid(): print(图层无效检查路径和字段名) else: QgsProject.instance().addMapLayer(layer) print(加载成功共, layer.featureCount(), 个点)这个例子展示了delimitedtext这个数据提供器的用法。注意delimiter,是逗号分隔符crs必须明确指定。要是CSV没有坐标只有属性QGIS也可以加载但会是一个“无几何图形”的表图层不能显示在地图上。加载成功后如果你要编辑依然走startEditing()三步曲。但要记住CSV是纯文本文件QGIS不支持原地修改CSV文件本身所以编辑通常要“另存为”一个GeoPackage或Shapefileoptions QgsVectorFileWriter.SaveVectorOptions() options.driverName GPKG error QgsVectorFileWriter.writeAsVectorFormatV3(layer, /path/to/out.gpkg, QgsCoordinateTransformContext(), options) if error[0] QgsVectorFileWriter.NoError: print(导出成功)3.3 复现官方示例根据拐点坐标创建多边形假设你手里有一串拐点坐标想把它们做成一个面图层。这个需求在土地调查、规划领域特别常见。官方例子的实现思路是这样的from qgis.core import QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, QgsPointXY coords [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], ] # 转成QgsPointXY列表 points [QgsPointXY(x, y) for x, y in coords] # 创建内存多边形图层 layer QgsVectorLayer(Polygon?crsEPSG:4326, area_from_coords, memory) QgsProject.instance().addMapLayer(layer) layer.startEditing() feat QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPolygonXY([points])) layer.addFeature(feat) layer.commitChanges() # 验证面积需要投影到米制坐标系 area feat.geometry().transform(QgsCoordinateReferenceSystem.fromEpsgId(3857)).area() print(面积平方米:, area)这里有个关键点经纬度坐标下不能直接算面积。因为EPSG:4326的单位是度面积单位是“平方度”毫无意义。官方例子的做法是投影到Web MercatorEPSG:3857后再算面积虽然精度一般但符合大多数场景。如果你要高精度面积建议用投影坐标系比如CGCS2000的EPSG:4543适用于北京地区。创建多边形时fromPolygonXY的入参是一个“环列表”即[points]。如果多边形带洞你需要写成[外环点列表, 内环点列表]。新手最容易忘的是闭合问题——其实QGIS的fromPolygonXY会自动帮你闭合你只需要提供不重复首尾顶点的列表就行。3.4 复现官方示例将线要素分割成两段“qgis将线要素分成两段”也是一个高频需求。官方例子的原理是用QgsGeometry的splitGeometry方法在一个指定点处把线切开from qgis.core import QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, QgsPointXY line_layer QgsVectorLayer(LineString?crsEPSG:3857, line, memory) QgsProject.instance().addMapLayer(line_layer) line_layer.startEditing() feat QgsFeature(line_layer.fields()) line_geom QgsGeometry.fromPolylineXY([ QgsPointXY(0, 0), QgsPointXY(100, 0) ]) feat.setGeometry(line_geom) line_layer.addFeature(feat) line_layer.commitChanges() # 获取要素并求交点 feature next(line_layer.getFeatures()) split_point QgsPointXY(50, 0) # 要在(50, 0)处切开 # splitGeometry 返回(拆分后的几何列表, 在拆分点新增的顶点点列表, 是否成功) parts line_geom.splitGeometry([split_point], True) if parts[2]: print(拆分成功得到, len(parts[0]), 段) for part in parts[0]: print(part.asWkt()) else: print(拆分失败)注意splitGeometry的这个签名在QGIS 3.20以后有微调官方例子通常会检查返回的第三个值布尔值来判断是否成功。如果拆分失败常见原因是拆分点不在几何内部比如点距离线太远。拆分之后如果你希望把多段线保存成同一个图层里的多个要素还需要遍历parts[0]逐个addFeature。3.5 复现官方示例批量构建金字塔与GeoPackage导出栅格图层的“构建金字塔”是官方例子里的一个常见专题。用代码构建金字塔主要是为了大影像加载时的显示性能。官方API用法是from qgis.core import QgsRasterLayer raster QgsRasterLayer(/path/to/landsat.tif, landsat, gdal) if not raster.isValid(): print(栅格无效) else: # 构建金字塔重采样算法项可以用 average/nearest/gauss raster.buildPyramids([], internal, average) print(金字塔构建完成)buildPyramids的三个参数分别是金字塔级别列表空列表表示使用默认级别、存储方式internal表示写入TIFF内部external则生成.ovr文件、重采样方法。这个操作适合对超大影像批量处理比如一整个目录几十个GeoTIFF脚本遍历一遍就全建好金字塔了比在QGIS界面里一个个右键“构建金字塔”高效得多。我自己处理过一批总大小约200GB的无人机正射影像用这个脚本批量建金字塔几台机器并行跑一晚上搞定。友情提醒构建金字塔时要先确认磁盘空间外部金字塔(.ovr)会额外占原始大小的5%到15%内部金字塔则直接增大TIFF文件体积。4. 常见问题与排查技巧实录4.1 怀疑“官方例子路径找不到”怎么办很多人第一反应是去GitHub上搜但其实最靠谱的办法是以你的本地安装为准。国内安装的Linux发行版QGIS的Python插件路径一般在/usr/share/qgis/python/plugins。Windows用户通常走的是安装向导路径形如C:\Program Files\QGIS 3.34\apps\qgis\python\plugins。macOS下如果你用Homebrew装的路径一般是/opt/homebrew/share/qgis/python/plugins。如果实在找不到也可以直接在QGIS的Python控制台里执行import processing print(processing.__file__)这个文件路径会指向Processing插件的实际安装目录官方算法模块就在它的上一级或者附近。4.2 独立脚本一运行就报错找不到QGIS核心库这是最常见的坑。症状是你已经安装了QGIS但在终端里python test.py却报ModuleNotFoundError: No module named qgis.core。原因不复杂你的Python解释器不知道QGIS库在哪里。解决办法有两种使用QGIS自带的Python环境通常在Windows下是“OSGeo4W Shell”在Linux下直接python3可能就能用如果你装的是系统包。如果是自编译或非系统包安装可以这样手动把路径加进去import sys sys.path.append(/usr/share/qgis/python) sys.path.append(/usr/share/qgis/python/plugins)我个人建议Windows用户优先用OSGeo4W Shell来运行脚本这样环境变量自动配好能省掉很多路径问题。4.3 坐标系与投影导致的诡异结果官方例子里经常出现面积计算为0、几何显示位置不对、叠加分析不出结果等情况80%是坐标系问题。我给你一个常规排查清单图层属性里的CRS是否设置正确鼠标放到图层上看“坐标系”那一行。几何数据本身是不是带EPSG:4326经纬度但图层却设成了EPSG:3857做几何运算前是否用transform(QgsCoordinateReferenceSystem.fromEpsgId(...))统一坐标系实测下来最稳妥的做法是所有中间计算统一用EPSG:3857Web Mercator数据存库或导出时再转回原始坐标系。这个策略在官方很多算法里也能看到比如距离计算、缓冲区分析都会先投影再算。4.4 MXD文件和DWG文件加载失败“qgis怎么打开mxd”这个需求我隔三差五就能遇到坦白说QGIS本身并没有原生支持MXD格式。你只能用ArcGIS的导出功能把MXD转成lyr或GeoPackage再传给QGIS。比较新的ArcGIS Pro版本支持导出到GeoPackage老的MXD计划只能先保存成.mxd再手动转。还有个办法是在QGIS中用qgis2web或者“导入”菜单下的某些插件但兼容性都不理想。我建议你直接跟提供MXD文件的同事要原始数据shapefile、GeoPackage、FGDB比任何转换都靠谱。DWG文件也是同样的道理。QGIS对DXF支持良好ogr驱动能直接读取DWG需要先借助外部工具转成DXF然后再读取。网上有人推ODA File Converter免费转换器实测下来转换大尺寸DWG会丢属性慎用。4.5 调试技巧善用print和QgsMessageLog官方插件代码在调试时经常会用QgsMessageLog.logMessage()来输出日志而不是简单的print()。因为print()在某些运行环境下不会显示在QGIS面板里而QgsMessageLog会输出到“信息日志”面板。from qgis.core import QgsMessageLog QgsMessageLog.logMessage(调试信息, MyPlugin, Qgis.Info)使用小记第一个参数是消息内容第二个是日志分组名可以自定义方便过滤第三个是日志级别。在开发插件时我都用这套方法来输出调试信息到了正式发布时再关掉。5. 一条更省力的“抄作业”路径从Processing算法中学写插件最后说一个我从官方例子里领悟到的高效思路把Processing算法当成一个“官方写好的插件模板”来学。一个Processing算法的基本结构是这样的class MyAlgorithm(QgsProcessingAlgorithm): def initAlgorithm(self, configNone): self.addParameter(QgsProcessingParameterVectorLayer(INPUT, 输入图层)) def processAlgorithm(self, parameters, context, feedback): source self.parameterAsSource(parameters, INPUT, context) # ... 处理数据 ... return {OUTPUT: outputLayer} QgsProcessing.registerAlgorithm(MyAlgorithm(), myplugin:myalgorithm)这个模板在官方所有算法里都大同小异。你只要套这个壳里面写自己的业务逻辑QGIS工具栏里就会出现一个可以带参数运行的工具。这比从头写一个插件要少掉很多样板代码界面和参数对话框都是自动生成的。学习时你可以挑这几个官方算法逐行读buffer.py简单参数传递、clip.py多图层输入输出、fieldcalculator.py操作字段表达式——这三个读完你基本就知道插件开发的门道了。6. 从官方例子到进阶怎么把这些代码沉淀成自己的工具箱6.1 搭建个人的代码片段库我个人的习惯是每学习一个官方例子就把代码整理成一个带注释的.py文件按功能分类放到自己的代码仓库里。比如“处理矢量”“处理栅格”“坐标系变换”“地图出图”。几年下来这个库已经几百个文件很多项目直接用里面的函数根本不用重新写。整理的时候注意三点一是统一使用QGIS3的API不要再写QgsVectorLayerV2这种过时写法二是每个函数都要有完整的中文注释说明参数含义和使用场景三是遇到好的官方例子里没有的小技巧比如某种writeAsVectorFormatV3的复杂参数单独记到一个“疑难杂症.md”里。6.2 巧用QGIS内置的“脚本生成器”QGIS里有一个“工具箱 → 图形处理模型”的功能你可以把手动操作组合成一个模型然后“导出为Python脚本”。这相当于让QGIS帮你自动生成PyQGIS代码是一位天然的“官方例子生成器”。我经常用这个方式处理重复任务比如“加载多张栅格、统一裁剪、导出到同一目录”。先在模型设计器里拖一遍然后导出成Python脚本再手动优化成带参数和循环的版本。这个方法对新手特别友好因为你能直观看到每步操作对应哪些API。6.3 不要再踩的坑版本兼容学习官方例子时特别要注意你手头QGIS的版本。QGIS 3.x 内部API变化很快比如QgsProperty、QgsFeatureRequest的参数、QgsProcessingFeedback的输出方式在不同小版本里都有差别。一个比较实际的建议是查官方文档时先把右上角的版本切换成你安装的版本再复制代码否则极有可能跑不通。我的经验是教程用的3.28LTR和3.34或3.36的API差别很大尤其是QgsVectorFileWriter.WriteFileError这类返回值的处理方式。6.4 利用官方插件目录学做界面如果你想进阶到带界面的插件开发不要去看别人的博客讲一大堆PyQt5基础直接翻官方插件源码。我特别喜欢看processing插件自带的UI代码以及db_manager插件的树形列表代码它们把QGIS的QgsDockWidget、QgsFileWidget等专用控件用得炉火纯青。照着这些代码复刻一遍你会对“如何在QGIS里做界面”有最直接的理解。我自己在做地图数据检查工具时就是拿着官方插件里的QgsMapToolIdentify与QgsMessageBar配合的代码改巴改巴就上项目了效率极高。写在最后可能有人会觉得啃官方例子长得慢不如直接看视频课程来得快。但我的实战经验正好相反视频看完觉得会了一到自己动手还是脑袋空空而源码拆真的能让你的肌肉记忆形成“API感”。我当年转型做QGIS二次开发的时候第一个月就是坐在电脑前把Processing算法的核心代码一行一行打印出来看不懂就查文档、跑测试。这个过程虽然慢但基础打得特别扎实后来写任何脚本都不心虚。几个实操阶段建议先从加载图层、遍历要素这种十行代码的小例开始跑通后立刻改造成自己的数据场景然后尝试改Processing算法最后才是写一个完整工具。中间遇到任何print输出不对、坐标系报错就回看官方同类代码是怎么处理的——这比到处搜博客靠谱得多因为官方代码永远跟你的QGIS版本最贴合。希望这篇文章能帮你把“qgis官方例子学习代码”这条路走得更顺一点。如果你在拆官方例子的过程中也踩了什么有意思的坑欢迎在评论区分享大家一起避雷。本文还有配套的精品资源点击获取