开发QGIS插件时,首先接触到的就是QgisInterface这个类。本文首先将概括的介绍QgisInterface这个核心接口类,然后再根据不同开发场景,分类讨论。
概括说明
QgisInterface是QGIS Python API (PyQGIS)中的一个抽象基类,用于访问和控制正在运行的 QGIS 桌面应用程序。它充当插件和脚本与 QGIS 主页面界面(包括地图画布、菜单和工具栏)交互的中心枢纽。
在QGIS的Python开发环境中,QgisInterface实例作为iface变量提供。这个变量会自动传递给任何Python插件的initGui()方法,从而允许二次开发人员以PyQt为基础,添加自定义功能。实现QGIS扩展。
代码示例,修改QGIS软件标题:
# 获取QGIS主程序
main_window = iface.mainWindow()
# 获取当前主程序标题
current_title = main_window.windowTitle()
# 自定义标题
new_title = current_title.replace('QGIS', 'My Customized QGIS')
main_window.setWindowTitle(new_title)
事件触发
命名规则:action***
说明:QgisInterface提供了两类触发事件。一类是信号方式,另一类是返回指定事件的QAction对象。信号方式更多的传递了QGIS框架的一些核心事件,如初始化完毕、应用程序显示风格修改、创建新工程等。QAction对象方式主要是各类子功能的事件,如漫游事件、量算事件等。
场景:监测图层编辑状态,实现图层编辑保存功能
示例代码:
from qgis.core import QgsProject
from qgis.gui import QgisInterface
from qgis.PyQt.QtWidgets import QAction
from qgis.PyQt.QtCore import Qt
class LayerEditManager:
def __init__(self, iface: QgisInterface):
self.iface = iface
self.edit_action = None # 我们将管理的编辑相关QAction
# 创建示例QAction
self.setup_actions()
# 连接信号
self.connect_signals()
# 初始化状态
self.update_action_state()
def setup_actions(self):
"""创建并设置QAction"""
self.edit_action = QAction("保存编辑")
self.edit_action.triggered.connect(self.save_edits)
# 将动作添加到界面
self.iface.addToolBarIcon(self.edit_action)
def connect_signals(self):
"""连接相关信号"""
# 监听当前图层变化
self.iface.currentLayerChanged.connect(self.on_current_layer_changed)
# 监听项目图层变化(图层添加/删除)
QgsProject.instance().layersAdded.connect(self.on_layers_changed)
QgsProject.instance().layersRemoved.connect(self.on_layers_changed)
# 通过QgisInterface获取编辑相关的QAction
# 这里以"Toggle Editing"动作为例,监听其状态变化
toggle_edit_action = self.iface.actionToggleEditing()
if toggle_edit_action:
toggle_edit_action.toggled.connect(self.on_edit_toggled)
def on_current_layer_changed(self, layer):
"""当前图层变化时的处理"""
self.update_action_state()
def on_layers_changed(self):
"""图层列表变化时的处理"""
self.update_action_state()
def on_edit_toggled(self, checked):
"""编辑状态切换时的处理"""
self.update_action_state()
def update_action_state(self):
"""更新QAction的可用状态"""
current_layer = self.iface.activeLayer()
# 只有当有当前图层且是矢量图层且处于编辑状态时,才启用保存动作
is_enabled = (current_layer is not None and
current_layer.type() == current_layer.VectorLayer and
current_layer.isEditable())
self.edit_action.setEnabled(is_enabled)
# 可选:根据状态改变文本
if is_enabled:
self.edit_action.setText("保存编辑")
else:
self.edit_action.setText("保存编辑(不可用)")
def save_edits(self):
"""保存编辑的示例方法"""
current_layer = self.iface.activeLayer()
if current_layer and current_layer.isEditable():
# 这里执行保存操作
current_layer.commitChanges()
self.iface.messageBar().pushMessage("成功", "编辑已保存", level=Qgis.Success, duration=3)
# 初始化插件时创建管理器
def init_layer_edit_manager(iface):
global edit_manager
edit_manager = LayerEditManager(iface)
return edit_manager
操作入口挂接
命名规则:addPlugin*、addToolbar、addDockWidget、unregister**
说明:将菜单、工具栏或停靠栏挂接到QGIS主程序,或从中移除菜单、命令等。
场景:在QGIS中添加菜单和工具栏,并接收命令
示例代码:
from qgis.PyQt.QtWidgets import QAction, QMenu
from qgis.PyQt.QtGui import QIcon
from qgis.core import QgsApplication, QgsMessageLog
from qgis.gui import QgisInterface
class MyPlugin:
def __init__(self, iface: QgisInterface):
# 保存接口引用
self.iface = iface
# 初始化动作列表
self.actions = []
# 初始化菜单
self.menu = None
# 初始化工具栏
self.toolbar = None
def initGui(self):
"""在QGIS界面中创建插件菜单和工具栏"""
# 创建插件主菜单
self.menu = QMenu("我的插件")
self.iface.pluginMenu().addMenu(self.menu)
# 创建工具栏
self.toolbar = self.iface.addToolBar("我的插件工具栏")
self.toolbar.setObjectName("MyPluginToolbar")
# 添加第一个命令动作
icon_path1 = ":/plugins/my_plugin/icon1.png" # 替换为实际图标路径
action1 = QAction(QIcon(icon_path1), "命令一", self.iface.mainWindow())
action1.triggered.connect(self.run_command1)
action1.setStatusTip("执行第一个命令")
action1.setWhatsThis("这是第一个命令的详细说明")
# 添加到菜单和工具栏
self.menu.addAction(action1)
self.toolbar.addAction(action1)
self.actions.append(action1)
# 添加第二个命令动作
icon_path2 = ":/plugins/my_plugin/icon2.png" # 替换为实际图标路径
action2 = QAction(QIcon(icon_path2), "命令二", self.iface.mainWindow())
action2.triggered.connect(self.run_command2)
action2.setStatusTip("执行第二个命令")
# 添加到菜单和工具栏
self.menu.addAction(action2)
self.toolbar.addAction(action2)
self.actions.append(action2)
# 添加分隔符
self.menu.addSeparator()
self.toolbar.addSeparator()
# 添加第三个命令动作(仅在菜单中显示)
action3 = QAction("仅菜单命令", self.iface.mainWindow())
action3.triggered.connect(self.run_command3)
self.menu.addAction(action3)
self.actions.append(action3)
# 添加子菜单示例
submenu = QMenu("子菜单", self.iface.mainWindow())
self.menu.addMenu(submenu)
sub_action = QAction("子菜单命令", self.iface.mainWindow())
sub_action.triggered.connect(self.run_sub_command)
submenu.addAction(sub_action)
self.actions.append(sub_action)
def unload(self):
"""从QGIS界面移除插件创建的菜单和工具栏"""
# 移除菜单
if self.menu:
self.iface.pluginMenu().removeAction(self.menu.menuAction())
self.menu.deleteLater()
self.menu = None
# 移除工具栏
if self.toolbar:
self.iface.mainWindow().removeToolBar(self.toolbar)
self.toolbar.deleteLater()
self.toolbar = None
# 移除所有动作
for action in self.actions:
self.iface.removeToolBarIcon(action)
self.actions = []
def run_command1(self):
"""第一个命令的处理函数"""
self.iface.messageBar().pushMessage(
"我的插件", "执行了命令一", level=Qgis.Info, duration=3)
QgsMessageLog.logMessage("命令一被触发", "我的插件")
def run_command2(self):
"""第二个命令的处理函数"""
self.iface.messageBar().pushMessage(
"我的插件", "执行了命令二", level=Qgis.Info, duration=3)
QgsMessageLog.logMessage("命令二被触发", "我的插件")
def run_command3(self):
"""第三个命令的处理函数"""
self.iface.messageBar().pushMessage(
"我的插件", "执行了仅菜单命令", level=Qgis.Info, duration=3)
QgsMessageLog.logMessage("仅菜单命令被触发", "我的插件")
def run_sub_command(self):
"""子菜单命令的处理函数"""
self.iface.messageBar().pushMessage(
"我的插件", "执行了子菜单命令", level=Qgis.Info, duration=3)
QgsMessageLog.logMessage("子菜单命令被触发", "我的插件")
# 插件初始化函数
def classFactory(iface: QgisInterface):
"""返回插件类实例"""
return MyPlugin(iface)
地图操作
命名规则:mapCanvas
说明:QGIS的所有图上操作都由QgsMapCanvas提供。将QgsMapCanvas理解为一张地图画布。一个QGIS中,支持包含一个或多个地图画布。你在中心地图区域看到的所有内容,均由地图画布负责提供。同样,在地图上的交互操作(如移动地图、放大缩小等),也是由地图画布最先负责接收鼠标事件信号后,再由后续绘图器完成绘制。
场景:创建一个新地图,并添加在线底图。
示例代码:
from qgis.core import QgsProject, QgsRasterLayer, QgsCoordinateReferenceSystem
from qgis.gui import QgsMapCanvas
from qgis.PyQt.QtWidgets import QMessageBox
class MapManager:
"""地图管理器类,负责创建项目、添加底图和地图画布管理"""
def __init__(self, iface):
"""
初始化地图管理器
:param iface: QgisInterface实例,提供对QGIS界面的访问
"""
self.iface = iface
self.map_canvas = iface.mapCanvas()
self.current_layer = None
def create_new_project_with_basemap(self):
"""
创建新项目并添加高德卫星图底图
:return: 成功返回True,失败返回False
"""
try:
# 创建新项目
self.iface.newProject()
# 创建高德卫星图图层
amap_url = (
'type=xyz&url=https://webst01.is.autonavi.com/appmaptile?'
'style%3D6%26x%3D%7Bx%7D%26y%3D%7By%7D%26z%3D%7Bz%7D&zmax=18&zmin=0'
)
layer = QgsRasterLayer(amap_url, '高德卫星图', 'wms')
# 检查图层是否有效
if not layer.isValid():
QMessageBox.warning(
self.iface.mainWindow(),
"图层错误",
"无法加载高德卫星图图层,请检查网络连接或URL格式"
)
return False
# 设置图层坐标系为Web墨卡托(EPSG:3857)
crs = QgsCoordinateReferenceSystem("EPSG:3857")
layer.setCrs(crs)
# 添加到项目
QgsProject.instance().addMapLayer(layer)
# 设置当前图层
self.current_layer = layer
# 设置地图画布的坐标系
self.map_canvas.setDestinationCrs(crs)
# 设置地图画布的范围为图层范围
self.map_canvas.setExtent(layer.extent())
# 刷新地图画布
self.map_canvas.refresh()
# 显示成功消息
self.iface.messageBar().pushSuccess(
"成功",
"已创建新项目并加载高德卫星图底图"
)
return True
except Exception as e:
# 显示错误信息
QMessageBox.critical(
self.iface.mainWindow(),
"错误",
f"创建项目时发生错误: {str(e)}"
)
return False
def get_current_layer(self):
"""
获取当前底图图层
:return: 当前底图图层对象
"""
return self.current_layer
def zoom_to_full_extent(self):
"""缩放到图层完整范围"""
if self.current_layer:
self.map_canvas.setExtent(self.current_layer.extent())
self.map_canvas.refresh()
# 在插件中的使用示例
class MyPlugin:
def __init__(self, iface):
self.iface = iface
self.map_manager = None
def initGui(self):
"""初始化插件界面"""
# 创建创建新项目的动作
self.new_project_action = QAction(
QIcon(":/plugins/my_plugin/icons/new_project.png"),
"创建带底图的新项目",
self.iface.mainWindow()
)
self.new_project_action.triggered.connect(self.create_new_project)
self.new_project_action.setStatusTip("创建新项目并添加高德卫星图底图")
# 添加到工具栏和菜单
self.iface.addToolBarIcon(self.new_project_action)
self.iface.addPluginToMenu("我的插件", self.new_project_action)
# 初始化地图管理器
self.map_manager = MapManager(self.iface)
def unload(self):
"""卸载插件时清理资源"""
self.iface.removeToolBarIcon(self.new_project_action)
self.iface.removePluginMenu("我的插件", self.new_project_action)
self.new_project_action = None
self.map_manager = None
def create_new_project(self):
"""创建新项目的槽函数"""
success = self.map_manager.create_new_project_with_basemap()
if success:
# 可选:缩放到完整范围
self.map_manager.zoom_to_full_extent()
# 插件初始化函数
def classFactory(iface):
"""返回插件类实例"""
return MyPlugin(iface)
触发现有功能
命名规则:show***
说明:显示QGIS提供的现有功能。如显示布局对话框、显示设置对话框、显示属性框等。
场景:显示当前图层属性对话框
示例代码:
from qgis.core import QgsProject, QgsMapLayer
from qgis.PyQt.QtWidgets import QMessageBox, QAction
from qgis.PyQt.QtGui import QIcon
class LayerPropertiesManager:
"""图层属性管理器类,负责处理图层属性对话框的显示"""
def __init__(self, iface):
"""
初始化图层属性管理器
:param iface: QgisInterface实例,提供对QGIS界面的访问
"""
self.iface = iface
def show_active_layer_properties(self):
"""
显示当前活动图层的属性对话框
:return: 成功返回True,失败返回False
"""
try:
# 获取当前活动图层
current_layer = self.iface.activeLayer()
# 检查是否有活动图层
if not current_layer:
QMessageBox.information(
self.iface.mainWindow(),
"无活动图层",
"请先选择一个图层。"
)
return False
# 检查图层是否有效
if not current_layer.isValid():
QMessageBox.warning(
self.iface.mainWindow(),
"图层无效",
f"选中的图层 '{current_layer.name()}' 无效或无法访问。"
)
return False
# 显示图层属性对话框
self.iface.showLayerProperties(current_layer)
return True
except Exception as e:
# 显示错误信息
QMessageBox.critical(
self.iface.mainWindow(),
"错误",
f"打开图层属性时发生错误: {str(e)}"
)
return False
核心通用功能
说明:提供QGIS主程序相关的核心功能,如获取mainWindow、给消息栏发送消息等。
场景:给消息栏发送消息
示例代码:
def show_custom_message(self):
"""使用pushMessage方法显示自定义消息"""
# pushMessage方法的完整参数说明:
# title: 消息标题
# text: 消息正文
# level: 消息级别 (Qgis.Info, Qgis.Warning, Qgis.Critical, Qgis.Success)
# duration: 显示持续时间(秒),0表示一直显示直到用户关闭
self.iface.messageBar().pushMessage(
"自定义消息", # 标题
"这是一个自定义消息,显示5秒", # 消息内容
level=Qgis.Info, # 消息级别
duration=5 # 显示5秒
祝各位编码顺利!早日完工!早点下班!
使用QgisInterface的其他开发问题,欢迎大家留言交流或联系我们。转载须注明出处。