实习二 QGIS插件开发
2.1 任务要求
a)用C++语言编写qgis插件,实现带有x/y坐标的文本文件的地图显示。
- 用文件流fstream操作文本文件,读取其中的坐标数据。
- 基于QgsPlugin相关类派生出一个插件,并加到插件工厂中。
- 基于QgsVectorLayer创建一个点矢量图层vecLayer,将坐标数据形成要素添加vecLayer中,并将vecLayer添加到mapCavas中进行显示。
b)用python语言编写qgis插件,实现中文地名的解析与地图显示。
- 用文件流fstream操作文本文件,读取其中的地名文本数据。
- 基于python新建一个qgis功能插件。
- 利用腾讯地图服务api,解析地名形成坐标,并将坐标形成要素添加到点图层中进行显示。
2.2 完成过程
2.2.1 C++插件
QGIS的C++插件开发主要是在QGIS软件中新增一个插件,实现将txt文本中带有x/y坐标的文本文件转化为shp文件,加载到QGIS窗口中。具体操作步骤如下:
在确定需要进行 C++插件式开发的时候,结合 QGIS 的插件的特点,这是一种利用dll库进行开发的方式。具体来说,需要在 QGIS 进行以下的设置,也即修改工程的属性,将输出的文件的方式更改为以.dll 作为后缀名的文件。如图2.2.1-1所示
图2.2.1-1 修改配置类型
这里的设计插件采用的空的QT Widget 窗口,设计的窗口的显示内容如图中所示, 这里的窗口设置不同通过Qt Creator创建的,而是通过在代码中重新生成一个Qt Widget 来生成的,同时将其可视化出来,具体的插件的界面显示内容如图2.2.1-2所示。
图2.2.1-2 插件样式
在设计完成插件的界面显示内容之后,可以对原来的代码进行重新编译的操作。首先需要引入一些需要引用到的头文件,如图2.2.1-3所示。
图2.2.1-3 引用头文件
读取输入的文件中的坐标信息,并将读取到的点坐标存储起来。采用的容器是QVector这种动态数组,其中点的坐标对类型为QPointF。读取文件时候,打开的方式采用的是以只读的方式以及文本形式打开文件。在可以成功打开文件之后,采用文件流的方式读取文件中的数据。
文件中存储的坐标每一行都是以类似于“12,23”这种方式进行存储的,因此每一行选用“,”作为分割符,从而可以成功获取每一个点的坐标信息。代码如图2.2.1-4所示。
图2.2.1-4 坐标读取文件
在C++中创建点图层的方式与Python中是十分类似的,不同之处在于在Python中使用GDAL库创建shp文件的时候,需要显式地进行驱动的注册。但是在C++中可以直接通过调用QGIS的接口来隐去部分操作。
具体来说,在C++中首先是注册了一个点矢量图层,之后在点矢量图层中创建了一系列的字段并提交了更改。之后根据上面已经得到的文件中的各个点的坐标数组,对其进行遍历。创建相应的feature,为每一个要素设置对应的字段信息以及相应的几何信息、属性信息。之后将每一个要素的信息添加到图层组的要素信息组中。最后调用QgsVectorFileWriter()函数实现shp文件的创建。主要需要传入的参数包括图层信息,输出文件名,编码格式,坐标系统信息以及矢量文件的格式信息等。至此,一个点矢量图层即已被成功创建。代码如图2.2.1-5所示。
图2.2.1-5 shp文件创建
点击上方的运行,即可在对应项目文件下的Release文件夹中输出封装好插件功能的动态链接库“ceshi.dll”文件。如图2.2.1-6所示。
图2.2.1-6 编译测试插件
将编译输出得到的dll文件复制到QGIS安装文件夹的【apps】-【qgis-ltr】-【plugins】文件夹中,操作如图2.2.2-7所示。
图2.2.1-7 安装插件
至此,可以在 QGIS 中的菜单栏中看到加载的插件,如下图中的红框中所显示的内容,插件的名称叫做"test",点击按钮。至此,插件已经成功加载到对应的窗口位置中。在插件窗口中输入文件地址为“坐标.txt”,如图2.2.1-8所示。
图2.2.1-8 坐标文本文件
点击save 按钮,弹出选择存储文件结果的框,最终得到的shp文件的显示效果如图2.2.1-9所示。
图2.2.1-9 显示结果
2.2.2 Python插件
QGIS的python插件开发主要是在QGIS软件中新增一个插件geocode tool bar,实现将txt文本中地址数据,通过调用腾讯地理编码服务,解析成经纬度,并写入到shp文件,加载到QGIS窗口中。具体操作步骤如下:
首先,双击QGIS Deskopt启动QGIS软件,进入到主界面,依次在工具栏点击【插件】-【管理并安装插件】-【新插件】,搜索并安装“Plugin Builder”和“Plugin Reloader”。操作如图2.2.2-1所示。
图2.2.2-1 下载并安装插件
下载完两个插件后,可以在【已安装】中检查两个插件是否都安装配置好,如图2.2.2-2所示。
图2.2.2-2 检查插件情况
Tips:这里安装的两个插件,其中Plugin Builder是用来生成QGIS插件Python工程模板工具,而Plugin Reloader则是用来在QGIS中重新加载插件,对插件进行调试的工具。
由于本处应用的是Python进行相关的配置开发,故这里需要检查一下对应的的QGIS的Python版本。打开QGIS,点击Python 控制台图标,打开QGIS中的Python 控制台。输入“QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)”,运行后,即可得到相应的QGIS内置的Python安装位置,操作如图2.2.2-3所示。
图2.2.2-3 检查Python版本
接下来,打开PyCharm,依次点击【File】-【Settings】-【project:工程名】-【Python Interpreter】-【Add】,选择【Virtualenv Environment】中的“Existing environment”,“Interpreter”选择QGIS 3.34.10\bin下的“python-qgis-ltr.bat”文件,这个批处理文件把QGIS的Python环境都配置好了,只要把它设置为解释器,就不需要再配置别的环境变量了。然后点击ok即可。操作如图2.2.2-4所示。
图2.2.2-4 配置Python解释器
配置完成后,不难发现,在QGIS的预设中,就已经提供了GDAL和shapely、PyQt5等二次开发库。如图2.2.2-5所示。
图2.2.2-5 检查Python解释器
配置完成python的环境后,回到QGIS,在工具栏重要依次点击【插件】-【Plugin Builder】-【Plugin Builder】。然后填写好插件信息,点击next。操作如图2.2.2-6所示。
图2.2.2-6 填写插件信息
接下来填写插件说明,这里内容可以不必细纠,填写完点击next。操作如图2.2.2-7所示。
图2.2.2-7 插件说明
接下来,在【Template】选择“Tool button with dialog”,即带工具按钮的对话框。并填写【Text for the menu item】为“”,将【Menu】选择为“Plugins”,接下来这个插件会在工具的【Plugins】目录下。然后点击next。操作如图2.2.2-8所示。
图2.2.2-8 插件选择
这里的国际化、帮助、单元测试、帮助脚本等都默认勾选,点击next。操作如图2.2.2-9所示。
图2.2.2-9 插件勾选
接下来勾选“Flag the plugin as experimental”,标识为测试插件,别的保持默认就行,点击next。操作如图2.2.2-10所示。
图2.2.2-10 测试插件
最后是为创建的工程选择一个路径,路径是一个文件夹,点击“Generate”。操作如图2.2.2-11所示。
图2.2.2-11 创建插件位置
接下来,会弹出创建结果,即“You just built a plugin for QGIS!”如图2.2.2-12所示。
图2.2.2-12 创建结果
完成新建插件的设置后,即可得到相应的项目文件夹,由于系统版本原因,这里已经预编译好了项目快捷文件“compile.bat”,并且也出现了对应的插件主体功能文件。如图2.2.2-13所示。
图2.2.2-13 项目文件夹
当然,该文件并没有成功的加入到QGIS的插件中,这里还需要将该文件夹复制到“C:\Users\33439\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins”中,再重启QGIS,依次打开工具栏的【插件】-【管理并安装插件】-【已安装】,才能看到新添加的插件。勾选上该插件即会发现该插件的工具图标也在界面上,如图2.2.2-14所示。
图2.2.2-14 新增插件
点击该插件,即可得到插件原始的预设样式,如图2.2.2-15所示。
图2.2.2-15 插件初始打开样式
进行完如上操作,插件的雏形已经有了,接下来要在这个雏形的基础上开发。在开发之前,首先需要把界面重新设置一下。这里可以直接打开文件夹,选择geocode_tool文件夹下的geocode_tool_dialog_base.ui文件,使用QT Creator打开,在主界面选择【界面编辑器】,点击ok。操作如图2.2.2-16所示。
图2.2.2-16 打开ui文件
接下来,在左侧控件栏中,选择对应的控件拖拽到界面上,在右侧属性框中,修改控件的objectName。新增加的文本框和按钮的名称分别是lineEditTxt,lineEditShp,lineEditKey,pushButtonTxt,pushButtonShp。操作最终得到的ui如图2.2.2-17所示。
图2.2.2-17 修改后的ui
接下来,可以回到QGIS软件中检查一下UI是否已经成功被修改。在工具栏中依次打开【插件】-【Plugin Reloader】-【Configure】,打开【Configure Plugin Reloader】对话框。在【Select the plugin you want to reload】中选择“Geocode Tool“,点击ok。操作如图2.2.2-18所示。
图2.2.2-18 更新插件
更新完插件后,再点击一下插件,即可发现插件的UI已经成功更改,如图2.2.2-19所示。
图2.2.2-19 更新ui后的插件
显然,这里界面的ui只是一个壳子,没有槽函数响应信号,因此需要对功能函数进行编码,这里打开文件夹中的“geocode_tool.py”文件进行修改。
首先,需要引入QT库函数,如图2.2.2-20所示。
图2.2.2-20 引入库函数
接下来,新增两个方法select_input_file和select_output_file,用以读取txt文件和shp文件的路径。如图2.2.2-21所示。
图2.2.2-21 新增读写文件路径
完成之后,在run方法中,添加两行代码,调用select_input_file和select_output_file方法,点击pushButtonTxt和pushButtonShp按钮的时候触发。如图2.2.2-22所示。
图2.2.2-22 修改run函数添加按钮触发
接下来新增两个个方法,其中readTxt函数应用于读写txt文件,writeShp函数应用于读写shp文件。如图2.2.2-23所示。
图2.2.2-23 新增读写txt和shp函数
最后新增一个方法geoCode,用于调用腾讯地图API密钥,如图2.2.2-24所示。
图2.2.2-24 新增getcode函数
在run方法的if result后面添加需要执行的代码。如图2.2.2-25所示。
图2.2.-25 显示结果
其中完整的源代码将在2.4节中展示。此处不在赘述。
对代码编译完成后,将所有的文件保存,将插件再次更新,再次点击插件,将对应的txt文件和腾讯地图API密钥输入,选择好输出的shp文件地址,点击“确定”即可得到相应的解析地址。操作如图2.2.2-26所示。
图2.2.2-26 使用插件
在界面上可以看到出现的插件情况和相应的点已被成功解析。如图2.2.2-27所示。
图2.2.2-27 解析情况
同样,可以右键图层打开【属性】,将其【源】中的【数据编码】设置为“UTF-8”如图2.2.2-28所示。
图2.2.2-28 修改数据源
接下来,点击OK,将图层属性表打开,即可看到对应的点的属性信息,打开对应的txt文件发现相符合,如图2.2.2-29所示。
图2.2.2-29 属性表对应txt文件
2.3 结果展示
2.3.1 C++插件结果
QGIS的C++插件开发主要是在QGIS软件中新增一个插件,实现将txt文本中带有x/y坐标的文本文件转化为shp文件,加载到QGIS窗口中。插件如图2.3.1-1所示。
图2.3.1-1 插件样式
当我们使用插件,打开测试数据,并进行转换时,最终可以正确的解析得到两个点坐标的矢量文件,如图2.3.1-2所示。
图2.3.1-2 C++插件使用结果
2.3.2 Python插件结果
QGIS的python插件开发主要是在QGIS软件中新增一个插件geocode tool bar,实现将txt文本中地址数据,通过调用腾讯地理编码服务,解析成经纬度,并写入到shp文件,加载到QGIS窗口中。插件如图2.3.2-1所示。
图2.3.2-1 插件样式
当我们使用插件,打开测试数据,并进行转换时,最终可以正确的解析得到三个点坐标的矢量文件,如图2.3.2-2所示。
图2.3.2-2 Python插件结果
2.4 关键代码
2.4.1 C++插件代码
本处的关键代码为在Visual Studio中配置的文件“ceshi.cpp”中写入的应用QGIS二次开发实现坐标解析转换的源代码:
#include "ceshi.h"
#include "qfiledialog.h"
#include "qapplication.h"
#include "qgsproject.h"
#include "QgsVectorLayer.h"
#include "QgsVectorFileWriter.h"
#include "QString.h"
ceshi::ceshi(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
ceshi::~ceshi()
{}
void ceshi::on_actionOpenProject_triggered()
{
QString filename = QFileDialog::getOpenFileName(this, QStringLiteral("选择工程文件"), "", "QGIS project (*.qgs)");
QFileInfo fi(filename);
if (!fi.exists())
{
return;
}
QgsProject::instance()->read(filename);
m_curMapLayer = QgsProject::instance()->mapLayer(0);
}
QVector<QPointF> getcoordinates(QString myfile) {
QVector<QPointF> coordinates;
QFile file(myfile);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
QStringList parts = line.split(',');
if (parts.size() == 2) {
bool okX, okY;
double x = parts[0].toDouble(&okX);
double y = parts[1].toDouble(&okY);
if (okX && okY) {
coordinates.append(QPointF(x, y));
}
}
}
file.close();
return coordinates;
}
else {
// 如果文件无法打开,可以在这里打印错误信息或处理异常
qWarning() << "Could not open file:" << myfile;
return coordinates; // 返回空的 QVector
}
}
void ceshi::outputButton_clicked() {
// 获取输入文件路径
QString myfile = inputFilename->text();
QVector<QPointF> coordinates = getcoordinates(myfile);
// 创建一个新的点矢量图层
QgsVectorLayer* layer = new QgsVectorLayer("Point?crs=EPSG:4326", "pointLayer", "memory");
if (!layer->isValid()) {
qWarning() << "Layer creation failed!";
return;
}
// 添加属性字段
QgsField idField("id", QVariant::Int);
QgsFields fields;
fields.append(idField);
layer->dataProvider()->addAttributes(fields.toList());
layer->startEditing();
// 添加字段到图层
layer->addAttribute(idField);
layer->commitChanges();
layer->updateFields();
// 将点数据添加到图层中
int id = 1;
QgsFeatureList features;
QString myId = "id";
for (const QPointF& point : coordinates) {
QgsFeature feature;
feature.setFields(layer->fields());
feature.setAttribute(myId, id++);
feature.setGeometry(QgsGeometry::fromPointXY(QgsPointXY(point.x(), point.y())));
features.append(feature);
}
// 添加特征到图层
layer->dataProvider()->addFeatures(features);
layer->updateExtents(); // 更新图层范围
// 保存图层为 Shapefile
QString outputFilename = QFileDialog::getSaveFileName(window, tr("Save File"), "", tr("Shapefiles (*.shp)"));
if (!outputFilename.isEmpty()) {
if (!outputFilename.endsWith(".shp", Qt::CaseInsensitive)) {
outputFilename += ".shp";
}
QgsVectorFileWriter::writeAsVectorFormat(
layer, outputFilename, "UTF-8", layer->crs(), "ESRI Shapefile"
);
}
}
2.4.2 Python插件代码
本处的关键代码为在Pycharm中打开的文件“geocode_tool.py”中写入的应用QGIS二次开发实现坐标解析转换的源代码:
# -*- coding: utf-8 -*-
"""
/***************************************************************************
GeocodeTool
A QGIS plugin
地理编码工具
Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
-------------------
begin : 2022-10-11
git sha : $Format:%H$
copyright : (C) 2022 by tt
email : 1404167294@qq.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction, QFileDialog
from qgis.core import Qgis, QgsProject, QgsVectorLayer
from .geocode_tool_dialog import GeocodeToolDialog
import os.path
import requests
try:
from osgeo import gdal
from osgeo import ogr
from osgeo import osr
except ImportError:
import gdal
import ogr
import osr
class GeocodeTool:
"""QGIS Plugin Implementation."""
def __init__(self, iface):
"""Constructor.
:param iface: An interface instance that will be passed to this class
which provides the hook by which you can manipulate the QGIS
application at run time.
:type iface: QgsInterface
"""
# Save reference to the QGIS interface
self.iface = iface
# initialize plugin directory
self.plugin_dir = os.path.dirname(__file__)
# initialize locale
locale = QSettings().value('locale/userLocale')[0:2]
locale_path = os.path.join(
self.plugin_dir,
'i18n',
'GeocodeTool_{}.qm'.format(locale))
if os.path.exists(locale_path):
self.translator = QTranslator()
self.translator.load(locale_path)
QCoreApplication.installTranslator(self.translator)
# Declare instance attributes
self.actions = []
self.menu = self.tr(u'&Geocode Tool')
# Check if plugin was started the first time in current QGIS session
# Must be set in initGui() to survive plugin reloads
self.first_start = None
# noinspection PyMethodMayBeStatic
def tr(self, message):
"""Get the translation for a string using Qt translation API.
We implement this ourselves since we do not inherit QObject.
:param message: String for translation.
:type message: str, QString
:returns: Translated version of message.
:rtype: QString
"""
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass
return QCoreApplication.translate('GeocodeTool', message)
def add_action(
self,
icon_path,
text,
callback,
enabled_flag=True,
add_to_menu=True,
add_to_toolbar=True,
status_tip=None,
whats_this=None,
parent=None):
"""Add a toolbar icon to the toolbar.
:param icon_path: Path to the icon for this action. Can be a resource
path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
:type icon_path: str
:param text: Text that should be shown in menu items for this action.
:type text: str
:param callback: Function to be called when the action is triggered.
:type callback: function
:param enabled_flag: A flag indicating if the action should be enabled
by default. Defaults to True.
:type enabled_flag: bool
:param add_to_menu: Flag indicating whether the action should also
be added to the menu. Defaults to True.
:type add_to_menu: bool
:param add_to_toolbar: Flag indicating whether the action should also
be added to the toolbar. Defaults to True.
:type add_to_toolbar: bool
:param status_tip: Optional text to show in a popup when mouse pointer
hovers over the action.
:type status_tip: str
:param parent: Parent widget for the new action. Defaults None.
:type parent: QWidget
:param whats_this: Optional text to show in the status bar when the
mouse pointer hovers over the action.
:returns: The action that was created. Note that the action is also
added to self.actions list.
:rtype: QAction
"""
icon = QIcon(icon_path)
action = QAction(icon, text, parent)
action.triggered.connect(callback)
action.setEnabled(enabled_flag)
if status_tip is not None:
action.setStatusTip(status_tip)
if whats_this is not None:
action.setWhatsThis(whats_this)
if add_to_toolbar:
# Adds plugin icon to Plugins toolbar
self.iface.addToolBarIcon(action)
if add_to_menu:
self.iface.addPluginToMenu(
self.menu,
action)
self.actions.append(action)
return action
def initGui(self):
"""Create the menu entries and toolbar icons inside the QGIS GUI."""
icon_path = ':/plugins/geocode_tool/icon.png'
self.add_action(
icon_path,
text=self.tr(u'geocode tool bar'),
callback=self.run,
parent=self.iface.mainWindow())
# will be set False in run()
self.first_start = True
def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI."""
for action in self.actions:
self.iface.removePluginMenu(
self.tr(u'&Geocode Tool'),
action)
self.iface.removeToolBarIcon(action)
# 读txt文件
def readTxt(self, path_str):
f = open(path_str, 'r', encoding='utf-8')
flines = f.readlines()
address_list = []
for l in flines:
address_list.append(l.strip('\n'))
f.close()
return address_list
# 写shp文件
def writeShp(self, path_str, geocode_list):
# 支持中文路径
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
# 属性表字段支持中文
gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8")
# 注册驱动
ogr.RegisterAll()
# 创建shp数据
strDriverName = "ESRI Shapefile"
oDriver = ogr.GetDriverByName(strDriverName)
if oDriver == None:
return "驱动不可用:" + strDriverName
# 创建数据源
oDS = oDriver.CreateDataSource(path_str)
if oDS == None:
return "创建文件失败:" + path_str
# 创建一个多边形图层,指定坐标系为WGS84
papszLCO = []
geosrs = osr.SpatialReference()
geosrs.SetWellKnownGeogCS("WGS84")
# 线:ogr_type = ogr.wkbLineString
# 点:ogr_type = ogr.wkbPoint
ogr_type = ogr.wkbPoint
# 面的类型为Polygon,线的类型为Polyline,点的类型为Point
oLayer = oDS.CreateLayer("Point", geosrs, ogr_type, papszLCO)
if oLayer == None:
return "图层创建失败!"
# 创建属性表
# 创建id字段
oId = ogr.FieldDefn("id", ogr.OFTInteger)
oLayer.CreateField(oId, 1)
# 创建address、title、level字段
oAddress = ogr.FieldDefn("address", ogr.OFTString)
oLayer.CreateField(oAddress, 1)
oTitle = ogr.FieldDefn("title", ogr.OFTString)
oLayer.CreateField(oTitle, 1)
oLevel = ogr.FieldDefn("level", ogr.OFTInteger)
oLayer.CreateField(oLevel, 1)
oDefn = oLayer.GetLayerDefn()
# 创建要素
# 数据集
for index, f in enumerate(geocode_list):
oFeaturePolygon = ogr.Feature(oDefn)
oFeaturePolygon.SetField("id", index)
oFeaturePolygon.SetField("address", f['address'])
oFeaturePolygon.SetField("title", f['title'])
oFeaturePolygon.SetField("level", f['level'])
geomPolygon = ogr.CreateGeometryFromWkt(f['point'])
oFeaturePolygon.SetGeometry(geomPolygon)
oLayer.CreateFeature(oFeaturePolygon)
# 创建完成后,关闭进程
oDS.Destroy()
return "数据集创建完成!"
def run(self):
"""Run method that performs all the real work"""
# Create the dialog with elements (after translation) and keep reference
# Only create GUI ONCE in callback, so that it will only load when the plugin is started
if self.first_start == True:
self.first_start = False
self.dlg = GeocodeToolDialog()
# 点击按钮,确定路径
self.dlg.pushButtonTxt.clicked.connect(self.select_input_file)
self.dlg.pushButtonShp.clicked.connect(self.select_output_file)
# show the dialog
self.dlg.show()
# Run the dialog event loop
result = self.dlg.exec_()
# See if OK was pressed
if result:
# 获取txt文件路径,shp文件路径,腾讯key
txtname = self.dlg.lineEditTxt.text()
shpname = self.dlg.lineEditShp.text()
tencentkey = self.dlg.lineEditKey.text()
address_list = self.readTxt(txtname)
# 读txt文件中的内容,并将geocode结果写入shp
geocode_list = []
for address in address_list:
result = self.geoCode(address, tencentkey)
if result != None:
geocode_list.append(result)
self.writeShp(shpname, geocode_list)
# 将结果加载QGIS界面
layerName = shpname.split("/")[len(shpname.split("/")) - 1].replace(".shp", "")
vlayer = QgsVectorLayer(shpname, layerName, "ogr")
if vlayer.isValid():
QgsProject.instance().addMapLayer(vlayer)
else:
print("图层加载失败!")
pass
# 在QGIS界面上打印结果
self.iface.messageBar().pushMessage("成功", "加载图层:" + layerName, level=Qgis.Success, duration=3)
# 加载txt文件的路径
def select_input_file(self):
filename,_filter = QFileDialog.getOpenFileName(
self.dlg,"Select input file","","*.txt"
)
self.dlg.lineEditTxt.setText(filename)
# 导出shp文件的路径
def select_output_file(self):
filename,_filter = QFileDialog.getSaveFileName(
self.dlg,"Select output file","","*.shp"
)
self.dlg.lineEditShp.setText(filename)
# 调用腾讯geocode服务
def geoCode(self, address, key):
url = 'https://apis.map.qq.com/ws/geocoder/v1/?address=' + address + '&key=' + key
reponse = requests.get(url=url)
reponse.encoding = 'utf-8'
data = reponse.json()
try:
if data['status'] == 0:
return {'address': address, 'title': data['result']['title'],
'point': 'POINT(' + str(data['result']['location']['lng']) + ' ' + str(
data['result']['location']['lat']) + ')',
'level': data['result']['level']}
except BaseException as e:
print(e)