4

I wrote a simple plugin using Plugin Builder running QGIS 3 buffer process on selected layers/features. It works well, but if the plugin dialog window is closed and re-opened, multiple features get added instead of one (x2, x3, x4, x5, etc, depending on how often the dialog got re-opened).

Does anyone know how to clear the memory layers when the dialog close (X) button is pressed?

 def run(self): """Run method that performs all the real work""" if self.first_start == True: self.first_start = False self.dlg = PlugtestDialog() self.dlg.setWindowFlags(Qt.WindowStaysOnTopHint) self.dlg.layer_comboBox.clear() self.dlg.fieldwidth_comboBox.clear() # 1/ gets the list of all the layers loaded in QGIS: layers = [layer for layer in QgsProject.instance().mapLayers().values()] layer_list = [] layer_list.append('') for layer in layers: layer_list.append(layer.name()) #adds list of loaded layer to the drop-down self.dlg.layer_comboBox.addItems(layer_list) # 2/ if layers are loaded, check if there are selected features and select the layer if so. Returns associated fields. selected_layer = self.iface.activeLayer() if selected_layer is not None: selected_layer_name = selected_layer.name() features_count = selected_layer.selectedFeatureCount() index_number_selected_layer = layer_list.index(selected_layer_name) if features_count is not 0 and selected_layer is not None: self.dlg.layer_comboBox.setCurrentIndex(index_number_selected_layer) self.dlg.fieldwidth_comboBox.clear() selectedComboLayerText = self.dlg.layer_comboBox.currentText() selectedComboLayer = QgsProject.instance().mapLayersByName(str(selectedComboLayerText))[0] fields = [field.name() for field in selectedComboLayer.fields()] self.dlg.fieldwidth_comboBox.addItems(fields) # 3/ function to fill the list of field for the selected layer in the layer drop-down. Gets launched when layer drop-down menu changes def field_select(): #self.dlg.field_comboBox.clear() self.dlg.fieldwidth_comboBox.clear() selectedComboLayerText = self.dlg.layer_comboBox.currentText() #conditional to prevent 'list out of range' error in case the empty entry is selected again if selectedComboLayerText is '': self.dlg.fieldwidth_comboBox.clear() else: selectedComboLayer = QgsProject.instance().mapLayersByName(str(selectedComboLayerText))[0] fields = [field.name() for field in selectedComboLayer.fields()] self.dlg.fieldwidth_comboBox.addItems(fields) # This connects the function to the layer drop-down when changed. Update fields to show the fields from the associated layer in layer drop down self.dlg.layer_comboBox.currentIndexChanged.connect(field_select) self.dlg.fixed_Button.setChecked(True) #function to apply a buffer on selected feature def buffer_on_selected(): #selected_layer = self.iface.activeLayer() selectedComboLayerText = self.dlg.layer_comboBox.currentText() selectedComboLayer = QgsProject.instance().mapLayersByName(str(selectedComboLayerText))[0] spinbox_value = self.dlg.spinBox.value() if self.dlg.fixed_Button.isChecked() is True: buffer_option = self.dlg.spinBox.value() #dynamic (by field) if self.dlg.field_Button.isChecked() is True: field_radius = self.dlg.fieldwidth_comboBox.currentText() buffer_option = QgsProperty.fromExpression(field_radius) #dissolved? if self.dlg.dissolve_checkBox.isChecked() is True: dissolve_option = True else: dissolve_option = False #selected features: # Check if features are selected and if tick box is checked if selectedComboLayer.selectedFeatureCount() > 0 and self.dlg.only_selected_checkBox.isChecked() is True: #if there's already an ouput layer that is loaded, just update the layer: if QgsProject.instance().mapLayersByName('output'): buffer_function = processing.run("native:buffer",{'INPUT':QgsProcessingFeatureSourceDefinition(selectedComboLayerText,True),'DISTANCE':buffer_option,'SEGMENTS':5,'END_CAP_STYLE':0,'JOIN_STYLE':0,'MITER_LIMIT':2,'DISSOLVE':dissolve_option,'OUTPUT':'memory:'}) sourceLYR = buffer_function['OUTPUT'] destLYR = QgsProject.instance().mapLayersByName('output')[0] features2 = [] for feature in sourceLYR.getFeatures(): features2.append(feature) destLYR.startEditing() data_provider = destLYR.dataProvider() data_provider.addFeatures(features2) destLYR.commitChanges() #if not, create output else: buffer_function = processing.run("native:buffer",{'INPUT':QgsProcessingFeatureSourceDefinition(selectedComboLayerText,True),'DISTANCE':buffer_option,'SEGMENTS':5,'END_CAP_STYLE':0,'JOIN_STYLE':0,'MITER_LIMIT':2,'DISSOLVE':dissolve_option,'OUTPUT':'memory:'}) QgsProject.instance().addMapLayer(buffer_function['OUTPUT']) #if not, create buffer for all features in the selected layer else: parameters = {'INPUT':selectedComboLayer, 'DISTANCE':buffer_option, 'SEGMENTS':5, 'END_CAP_STYLE':0, 'JOIN_STYLE':0, 'MITER_LIMIT':2, 'DISSOLVE':dissolve_option, 'OUTPUT':'memory:'} buffer_function = processing.run("native:buffer", parameters) # show the dialog self.dlg.show() self.dlg.BigButton.clicked.connect(buffer_on_selected) 
2
  • 1
    You should post some code for the main part of your plugin to allow the community to see where the problem could lie. But I would probably suggest that you create/edit a function which gets executed when the dialog closes which deletes any instances of the memory layer (e.g. del mem_layer or whatever you named it.) Commented Jan 25, 2019 at 10:53
  • I'd really like to clear the memory outputs when the dialog gets closed but I didn't find the right way to do it. What function name does the Close (x) button has? I also can't figure a way to delete if only buffer['output'] exists. What to do to avoid returning an error if no layer exist? Commented Jan 30, 2019 at 2:35

1 Answer 1

1

Plugin Builder does check for first_start. All pushButtons should be placed there to avoid multiple launches if the plugin dialog is open/closed multiple times.

self.dlg.BigButton.clicked.connect(buffer_on_selected)

should be placed at the beginning of def run(self):

if self.first_start == True: self.first_start = False self.dlg = PlugtestDialog() self.dlg.setWindowFlags(Qt.WindowStaysOnTopHint) self.dlg.BigButton.clicked.connect(buffer_on_selected) <-----

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.