原文地址:QGis插件编写-GeocodeCN
QGis插件编写记录-GeocodeCN
这是实习期间写的一个工具,目的是为了将地址转为坐标点(地理编码),刚开始只是一小段Python脚本,批量请求百度地图开放接口进行编码,这确实满足了我的需求,不过每次编码都需要生成csv文件后再导入GSI软件生成矢量点图层查看,还是不够简单高效,于是萌生将其集成到QGis的想法。QGis现存地理编码插件,我所知道的,一般是请求开放街道地图(OSM)的服务,总所周知,OSM作为国外地理数据提供者,可能会存在关于我国领土边界的问题,所以决定自行写一个。
1.目标
- 批量获取感兴趣地址点的百度坐标。
- 自动生成点图层。
2.准备
在开始编写之前需要做如下准备:
2.1 安装插件
构造插件——PluginBuildet,重载插件——PluginReloader
上述两个插件在官方插件仓库里没有获取到,只能在官网上以将其下载下来,然后以离线方式安装,地址:https://plugins.qgis.org/
2.2 配置UI工具
UI工具可以是QtCreator或者QtDesigner,后边要修改UI页面文件,我使用的Qgis版本为3.22.0,已经自带QtDesigner,没必要再单独配置。
3.过程
3.1 生成插件模板
打开安装好的PluginBuilder插件,按照提示把相关信息填写好
最后选择保存文件位置,生成相关模板文件。
3.2 插件结构
这是官网展示的插件结构图,每一个插件都包含下面所列的文件,关于每一个文件的意义也作了说明。
下图为PluginBuilder生成的模板,它包含了官网所列的必要文件,如果该插件移到Qgis插件目录下,重启后就能看到被加载到qgis里。
3.3 设计UI及编译资源
启动QtDesigner,打开GeocodeCn_dialog_base.ui文件,根据需求设计界面元素。原始界面只包含【确认】和【取消】按钮,下图已设计好。
GeocodeCN_dialog.py文件会自动将UI文件编译为python类,不建议修改UI文件名称、以及GeocodeCN_dialog的代码,除非清楚如何修复它。
新设计一个格式为.png的图标文件,替换模板中的icon.png,它是插件的图标。
图标经过编译为.py文件之后,才能引用,感觉资源编译这一块问题出得比较多,因为网上蛮多人在问,目前所知的方法如下:
前两个模块提供有命令行编译,运行会报错,看起来不是用的QGis自带的解释器,而是本机的默认解释器,我文件移动到一个先前建好的虚拟环境里(前提是安装PyQt5),运行无问题。
我的编译方法是借助pyrcc,在PyCharm中使用pyrcc需要提前配置,具体步骤为:前往 Settings --> Tools --> External Tools
- Program为pyrcc.exe所在路径,一般在scripts路径下
- Arguments:设置为 F i l e N a m e FileName FileName -o F i l e N a m e W i t h o u t E x t e n s i o n FileNameWithoutExtension FileNameWithoutExtension_rc.py
- Working Directory: F i l e D i r FileDir FileDir
配置完成后,可以一键编译。 ![image-20220108222916870](https://img-blog.csdnimg.cn/img_convert/26e3349b6c384331dcbe5d7fc49e3ee3.png#pic_center)
下图是编译好的插件图标在QGis的显示效果。
3.4 环境配置
完成UI界面,准备编写逻辑代码,由于插件是在QGis自带Python解释器里执行,所以开始前先配置环境,便于引入相关依赖,此处参考知乎用户【才华横溢吴道简】3的文章。
进入Python控制台,输入如下代码,可以看到python解释器所在路径
QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)
在PycCharm中打开模板所在文件夹,选择 Settings --> Project --> Project Interpreter
设置路径为bin文件夹下的【python-qgis.bat],该批处理文件把QGIS的Python环境都配置好,只要把它设置为解释器,就不需要再配置别的环境变量。
3.5 代码编写
完整代码可访问获取:https://gitee.com/ShihanW/geocode-cn
遇到的问题如下:
- QThread: Destroyed while thread is still running
类似代码如下:
原因是在cerate_thread方法内,th作为一个局部变量,在方法结束之后就结束期生命周期,但是线程仍在运行,可以修改th作为类属性成员。