QGis 3.x插件信号重复触发问题:如何正确断开信号?
QGIS 3.x插件信号重复触发问题解决方案
问题根源
你当前的代码中,每次调用run()方法都会执行self.dlg.push_button_start.clicked.connect(self.on_pb_start),但对话框实例self.dlg只创建一次,导致信号被重复连接,最终触发槽函数多次。
解决方案一:仅连接一次信号
将信号连接逻辑放在对话框初始化的代码块内,确保只执行一次:
修改my_plugin.py的run()方法:
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 = MyPluginDialog() # 仅在对话框首次创建时连接信号 self.dlg.push_button_start.clicked.connect(self.on_pb_start) # 显示对话框 self.dlg.show()
解决方案二:先断开再连接(动态场景适用)
如果需要在每次打开对话框时重新绑定信号,可以先尝试断开已有连接(捕获首次无连接的异常),再重新连接:
def run(self): """Run method that performs all the real work""" if self.first_start == True: self.first_start = False self.dlg = MyPluginDialog() try: # 尝试断开已有连接 self.dlg.push_button_start.clicked.disconnect(self.on_pb_start) except TypeError: # 首次无连接时忽略异常 pass # 重新连接信号 self.dlg.push_button_start.clicked.connect(self.on_pb_start) # 显示对话框 self.dlg.show()
在initGui()中访问对话框对象的方法
可以在initGui()阶段提前初始化对话框实例,这样就能直接访问UI元素:
修改my_plugin.py的initGui()和run():
def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/my_plugin/icon.png' self.add_action( icon_path, text=self.tr(u'Start My Plugin'), callback=self.run, parent=self.iface.mainWindow()) # 提前初始化对话框 self.dlg = MyPluginDialog() # 直接在这里连接信号或访问UI元素 self.dlg.push_button_start.clicked.connect(self.on_pb_start) def run(self): """Run method that performs all the real work""" # 直接显示对话框 self.dlg.show()
插件关闭时自动断开所有信号
在unload()方法中销毁对话框实例,Qt会自动处理所有信号的断开:
def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" self.remove_action(self.action) # 销毁对话框,自动断开所有信号 if hasattr(self, 'dlg'): self.dlg.close() self.dlg.deleteLater() del self.dlg
内容的提问来源于stack exchange,提问作者Beinje
相关产品推荐
相关产品推荐

