我正在为QGis 3.x开发一个插件。UI是由Plugin builder
使用Qt Designer和插件代码样板创建的。
我的项目中有3个主要文件:
my_plugin.py
,具有主MyPlugin
类和initGui()
、unload()
和run()
方法my_plugin_dialog.py
带有一个简单的MyPluginDialog
类,它继承了基于我的.ui
设计器文件的QtWidgets.QDialog
和FORM_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)
...