17.2. 开发第一个插件#
当你想实现交互式工具或者非常特殊的图形用户界面时,是时候研究插件开发了。
在前面的练习中,我们介绍了QGIS Python API。
因此,我们现在可以专注于启动第一个QGIS插件的必要步骤。
为QGIS创建插件的好处是有一个插件!它叫插件生成器。
当你在那里的时候,也要安装 插件重载器
,这对插件开发人员非常有用。
因为它可以让你快速地重新加载你的插件,而不必每次你对代码进行修改时都重新启动QGIS。
当您安装了两个插件后插件工具栏将如下所示 图 17.3 。

图 17.3 插件工具栏#
在开始之前,我们还需要安装设计器 ,这是我们用来设计用户界面的应用程序。如果你使用Windows, 我建议 WinPython ( http://winpython.github.io/ )版本3.12.10(编写本书时Python 3.12的最新版本), 它提供Qt设计器和斯派德(Python的集成开发环境)。 在Ubuntu上,您可以使用sudo apt-get install qt4-designer。 在Mac上,你可以得到Qt创建者从 http://Qt-project.org/downloads 下载安装程序(包括Qt设计器)。
17.2.1. 使用plugin Builder创建插件模板#
Plugin Builder
将创建我们的插件所需的所有文件。要创建插件模板,请执行以下步骤:
1.起点插件生成器输入基本插件信息,包括:
类名 (第一个单词用大写,即每个单词以大写字母开头)
插件名称 (简短的描述)
模块名称 (插件的Python模块名)
将鼠标悬停在“插件生成器”对话框中的输入字段上时,将显示帮助信息, 如 图 17.4 所示。

图 17.4 插件生成器设置#
2.点击"Next"到达“关于”对话框,您可以在其中输入插件功能的更详细描述。因为我们计划创建第一个插件只用于学习目的, 所以我们可以在这里放置一些随机文本并单击"Next",如 图 17.5 所示。

图 17.5 插件生成器设置1#
3.现在我们可以选择一个插件模板并指定“菜单项的文本”以及"Menu"插件应该在中列出,如 图 17.6 所示。 可用的模板包括带对话框的工具按钮,带停靠小部件的工具按钮和处理提供程序。 在本练习中,我们将创建带对话框的工具按钮然后点击"Next",

图 17.6 插件生成器#
4.下面的对话框显示复选框,我们可以在其中选择应创建哪些非必需的插件文件。 您可以选择所提供选项的任何子集,然后单击"Next" ,如 图 17.7 。

图 17.7 插件生成器复选框#
5.在下一个对话框中,我们需要指定插件“窃听器” 还有“密码知识库”。同样,由于我们创建这个插件只是为了学习, 我只是在下一个截图中创建一些url,但是如果您打算公开您的插件,您应该使用适当的追踪器和代码库, 如 图 17.8 。

图 17.8 插件生成器复选框1#
6.一旦你点击"Next",将要求您选择一个文件夹来存储插件。 你可以直接保存在QGIS插件文件夹中,~.qgis2pythonplugins 在窗户上, 或 ~/.qgis2/python/plugins 在Linux和Mac上。如 图 17.9 。

图 17.9 插件生成器输出#
7.选择插件文件夹后,它将显示“插件生成器结果”确认对话框,它确认您的插件文件夹的位置以及您的QGIS插件文件夹的位置。 如前所述,我直接保存在QGIS插件文件夹中,如 图 17.10 所示。如果您已保存在其他位置, 现在可以将插件文件夹移动到QGIS插件文件夹中,以确保QGIS可以找到并加载它,

图 17.10 插件生成器结果#
我们仍然要做的一件事是为插件工具栏准备图标。 这需要我们编译"resources.qrc"文件,其中“插件生成器”自动创建, 将图标转换为可用的Python代码。这是在命令行上完成的。 在Windows上,我建议使用 "OSGeo 4W"外壳, 因为它确保环境变量的设置方式能够找到必要的工具。 导航到插件文件夹并运行以下命令:
pyrcc4 -o resources.py resources.qrc
您可以替换默认图标( icon.png )添加你自己的插件图标。 之后,你只需要重新编译"resources_rc.qrc"如前所示。
重新启动QGIS,您现在应该会看到插件管理器中列出了您的插件, 如 图 17.11 所示。

图 17.11 插件管理器#
在插件管理器中激活你的插件,你会看到它列在“插件”菜单。 当你启动你的插件时,它会显示一个空白对话框,等待你自定义它。
17.2.2. 自定义插件GUI#
要自定义空白默认插件对话框,我们使用“设计器”。 您可以在plugin文件夹中找到对话框文件。 在我的情况下,它被称为"my_first_plugin_dialog_base.ui"(派生自我在插件生成器中指定的模块名)。 当你打开你的插件时 .ui.用户界面在Qt设计器中,您将看到空白对话框。 现在您可以通过从小部件框"在Qt设计器窗口的左侧” 在下面的屏幕截图中,如 图 17.12 右下角所示。 你可以看到我添加了一个标签以及一个下拉列表小部件(列为组合框在小部件框公司 )。 您可以将标签文本更改为层双击默认标签文本。此外,为小部件对象分配描述性名称是一种很好的做法; 例如,我将组合框重命名为"layerCombo"。

图 17.12 设计器#
完成对插件对话框的更改后,可以保存它们。然后你可以回到QGIS。
在QGIS中,现在可以配置 插件重载器
点击 选择要重新加载的插件
按钮在插件工具栏并选择插件。
如果你现在点击 重新加载插件
按钮和按下你的插件按钮,你的新插件对话框将显示。
17.2.3. 实现插件功能#
正如您肯定注意到的,层组合框仍然是空的。要用加载的层列表填充组合框, 我们需要添加几行代码到"my_first_plugin.py"(位于“插件”文件夹)。 更具体地说,我们扩展了运行()方法:
定义运行(自):
“运行执行所有实际工作的方法”
# show the dialog self.dlg.show()
# clear the combo box to list only current layers
self.dlg.layerCombo.clear()
# get the layers and add them to the combo box layers =
QgsMapLayerRegistry.instance().mapLayers().values() for layer in
layers:
if layer.type() == QgsMapLayer.VectorLayer:
self.dlg.layerCombo.addItem(layer.name(),层)
# Run the dialog event loop result = self.dlg.exec_()
# See if OK was pressed if result:
# Check which layer was selected index =
self.dlg.layerCombo.currentIndex() layer =
self.dlg.layerCombo.itemData(index)
# Display information about the layer
QMessageBox.information(self.iface.mainWindow(),“学习
QGIS“,”%s有%d个功能。“%(layer.name(),layer.featureCount()))
您还必须在脚本顶部添加以下导入行以避免 NameErrors 关于 QgsMapLayerRegistry 和 QMessageBox :
from qgis.core import * from PyQt4.QtGui import QMessageBox
一旦你完成了对"my_first_plugin.py",
您可以保存文件并使用 重新加载插件
按钮重新加载你的插件。
如果现在启动插件,则组合框将填充当前QGIS项目中所有层的列表,当您单击 OK
,您将看到一个消息框,
其中显示选定图层中的要素数。
17.2.4. 创建自定义地图工具#
虽然上一个练习演示了如何创建一个自定义GUI,使用户能够与QGIS交互,但是在这个练习中, 我们将更进一步,实现我们自己的自定义地图工具类似于违约识别工具。 这意味着用户可以点击地图,工具报告地图上的哪个功能被点击了。
为此,我们创建了另一个带对话框的工具按钮插件模板调用"MyFirstMapTool"。 对于这个工具,我们不需要创建对话框。相反,我们必须比前面的例子写更多的代码。 首先,我们创建自定义映射工具类,我们称之为"IdentifyFeatureTool"。 除了"__init__() "构造函数,此工具有一个名为 画布发布事件()定义释放鼠标按钮时(即,按下鼠标按钮后松开鼠标按钮时)工具的操作:
class IdentifyFeatureTool(QgsMapToolIdentify): def __init__(self,
canvas): QgsMapToolIdentify.__init__(self, canvas) def
canvasReleaseEvent(self, mouseEvent):
打印“canvasReleaseEvent”
# get features at the current mouse position results =
self.identify(mouseEvent.x(),mouseEvent.y(),
self.TopDownStopAtFirst, self.VectorLayer) if len(results) > 0:
[# signal that a feature was identified self.emit( SIGNAL( "geomIdentified" ),
results[0].mLayer, results[0].mFeature)]
您可以将前面的代码粘贴到"my_first_map_tool.py"代码。 当然,我们现在必须好好利用我们的新地图工具。 在初始化用户界面()函数,我们替换运行()新方法"map_tool_init()"功能。 此外,我们定义我们的地图工具是可检查的; 这意味着用户可以单击工具图标来激活它,然后再次单击它来停用它:
def initGui(自身):
# create the toolbar icon and menu entry icon_path = ':/plugins
/MyFirstMapTool/icon.png' self.map_tool_action=self.add_action(
icon_path,
text=self.tr(u'My 1st Map Tool'), callback=self.map_tool_init,
parent=self.iface.mainWindow())
self.map_tool_action.setCheckable(True)
新的"map_tool_init()"功能负责在单击按钮时激活或停用我们的地图工具。 在激活过程中,它创建了一个自定义的实例"IdentifyFeatureTool", 以下行连接映射工具的“地质鉴定”向发送信号"do_something()"函数,稍后我们将讨论。 类似地,当"map"工具被停用时,我们会断开信号并恢复先前的"map"工具:
def map_tool_init(self):
# this function is called when the map tool icon is clicked print
"maptoolinit" canvas = self.iface.mapCanvas() if
self.map_tool_action.isChecked(): # when the user activates the tool
self.prev_tool = canvas.mapTool() self.map_tool_action.setChecked(
True ) self.map_tool = IdentifyFeatureTool(canvas)
QObject.connect(self.map_tool,SIGNAL("geomIdentified"),
self.do_something ) canvas.setMapTool(self.map_tool)
QObject.connect(canvas,SIGNAL("mapToolSet(QgsMapTool *)"),
self.map_tool_changed) else:
# when the user deactivates the tool
QObject.disconnect(canvas,SIGNAL("mapToolSet(QgsMapTool *)"
),self.map_tool_changed) canvas.unsetMapTool(self.map_tool) print
"restore prev tool %s" %(self.prev_tool)
canvas.setMapTool(self.prev_tool)
我们的新习惯"do_something()"当我们的地图工具被用来成功地识别一个特征时,函数被调用。 在本例中,我们只需在Python控制台。 当然,您可以在这里获得创意并添加所需的自定义功能:
def do_something(self, layer, feature): print feature.attributes()
最后,我们还必须处理当用户切换到其他地图工具时的情况。 这类似于用户在"map_tool_init()"函数:
def map_tool_changed(self): print "maptoolchanged" canvas = self.iface.mapCanvas()
QObject.disconnect(canvas,SIGNAL("mapToolSet(QgsMapTool *)"),
self.map_tool_changed) canvas.unsetMapTool(self.map_tool)
self.map_tool_action.setChecked(False)
您还必须在脚本顶部添加以下导入行,以避免与QObject,QgsMapTool ,以及其他:
**from qgis.core import * from qgis.gui import * from PyQt4.QtCore import ** *
当你准备好了,你可以重新加载插件并尝试它。
你应该有Python控制台 打开以便能够跟踪插件的输出。
当你激活工具栏中的插件时,你首先会看到它打印出来 映射工具初始化 在控制台上。
然后,如果你点击地图,它就会打印出来拉票活动 ,如果单击某个要素,它也将显示该要素的属性。
最后,如果您切换到另一个地图工具(例如, 泛地图
工具)它将打印地图工具已更改在控制台上,
插件工具栏中的图标将被取消选中。