QGis插件的断开信号与Qt设计器创建的对话框



我正在为QGis 3.x开发一个插件。UI是由Plugin builder使用Qt Designer和插件代码样板创建的。

我的项目中有3个主要文件:

  • my_plugin.py,具有主MyPlugin类和initGui()unload()run()方法
  • my_plugin_dialog.py带有一个简单的MyPluginDialog类,它继承了基于我的.ui设计器文件的QtWidgets.QDialogFORM_CLASS。该类只包含__init__()方法,该方法本身调用self.setupUi()
  • Qt设计器my_plugin_dialog_base.ui创建的UI文件

在启动/关闭插件对话框时,我遇到了一些与重复信号有关的问题。关于SO最相似的讨论如下:https://gis.stackexchange.com/questions/137160/qgis-plugin-triggers-function-twice

然而,我的问题是,我的对话框对象是在run()方法中创建的(见下文(,因此我无法访问initGui()unload()方法中的UI元素。

那么,我如何断开信号,或者定义它们,以便关闭插件也断开我所有的信号?

以下是my_plugin.py内容的摘录(Plugin Builder创建的,除了与连接信号和插槽相关的最后一行(:

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())
# will be set False in run()
self.first_start = True
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) # connect signal to slot

my_plugin_dialog.py:

FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'small_etl_dialog_base.ui'))
class MyPluginDialog(QtWidgets.QDialog, FORM_CLASS):
def __init__(self, parent=None):
"""Constructor."""
super(MyPluginDialog, self).__init__(parent)
# Set up the user interface from Designer through FORM_CLASS.
# After self.setupUi() you can access any designer object by doing
# self.<objectname>, and you can use autoconnect slots - see
# http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
# #widgets-and-dialogs-with-auto-connect
self.setupUi(self)

也许有一种正确的方法可以访问initGui()方法中的对话框对象?

之所以会发生这种情况,是因为每次调用run方法时都会连接信号。但是,您只创建一次由布尔变量保护的对话框。

解决方案是只在创建对话框时连接您的信号,这样做会更好:

def run(self):
...
if self.first_start == True:
self.first_start = False
self.dlg = MyPluginDialog()
self.dlg.push_button_start.clicked.connect(self.on_pb_start)
...

另外,请注意,您不一定需要self.first_start布尔保护。您可以随时检查self.dlg是否不是None

所以,你可以通过这样的东西来整理一下:

def run(self):
...
if not self.dlg:
self.dlg = MyPluginDialog()
self.dlg.push_button_start.clicked.connect(self.on_pb_start)
...

最新更新