Svarbu
Vertimas yra bendruomenės pastangos, prie kurių jūs galite prisijungti. Šis puslapis šiuo metu išverstas 32.14%.
17. Apdorojimo priedo rašymas
Priklausomai nuo to, kokį ruošiatės kurti priedą, gali būti geresnis variantas pridėti jo funkcionalumą kaip Apdorojimo algoritmą (arba jų aibę). Tai suteiktų geresnę integraciją QGIS viduje, papildomą funkcionalumą (kadangi jį galima būtų paleisti Apdorojimo komponentuose, tokiuose kaip modelyje arba paketinio apdorojimo sąsajoje). Tai taipogi leistų greitesnį kūrimą (kadangi Apdorojimas užims didžiąją darbo dalį).
Norėdami platinti tokius algoritmus, jūs turite sukurti priedą kuris prideda juos į Apdorojimo įrankinę. Priedas turi turėti algoritmo tiekėją, kuris turi būti registruotas kai sukuriama priedo kopija.
17.1. Kūrimas nuo nulio
Norėdami sukurti nuo nulio priedą, kuris turi algoritmo tiekėją, jūs galite vykdyti šiuos žingsnius, naudodami Priedų kūrėją:
Įdiekite Priedų kūrėjo priedą
Sukurkite naują priedą, naudodami Priedų kūrėją. Kai Priedų kūrėjas jūsų paprašys parinkti šabloną, parinkite „Apdorojimo tiekėjas“.
Sukurtas priedas turi tiekėja su vienu algoritmu. Tiek tiekėjo failas, tiek algoritmo failas yra pilnai komentuoti ir juose yra informacija apie tai, kaip keisti tiekėją bei pridėti papildomus algoritmus. Ten rasite daugiau informacijos.
17.2. Updating a plugin
If you want to add your existing plugin to Processing, you need to add some code.
In your
metadata.txtfile, you need to add a variable:hasProcessingProvider=yes
In the Python file where your plugin is setup with the
initGuimethod, you need to adapt some lines like this:1from qgis.core import QgsApplication 2from .processing_provider.provider import Provider 3 4class YourPluginName: 5 6 def __init__(self): 7 self.provider = None 8 9 def initProcessing(self): 10 self.provider = Provider() 11 QgsApplication.processingRegistry().addProvider(self.provider) 12 13 def initGui(self): 14 self.initProcessing() 15 16 def unload(self): 17 QgsApplication.processingRegistry().removeProvider(self.provider)
You can create a folder
processing_providerwith three files in it:__init__.pywith nothing in it. This is necessary to make a valid Python package.provider.pywhich will create the Processing provider and expose your algorithms.1from qgis.core import QgsProcessingProvider 2from qgis.PyQt.QtGui import QIcon 3 4from .example_processing_algorithm import ExampleProcessingAlgorithm 5 6class Provider(QgsProcessingProvider): 7 8 """ The provider of our plugin. """ 9 10 def loadAlgorithms(self): 11 """ Load each algorithm into the current provider. """ 12 self.addAlgorithm(ExampleProcessingAlgorithm()) 13 # add additional algorithms here 14 # self.addAlgorithm(MyOtherAlgorithm()) 15 16 def id(self) -> str: 17 """The ID of your plugin, used for identifying the provider. 18 19 This string should be a unique, short, character only string, 20 eg "qgis" or "gdal". This string should not be localised. 21 """ 22 return 'yourplugin' 23 24 def name(self) -> str: 25 """The human friendly name of your plugin in Processing. 26 27 This string should be as short as possible (e.g. "Lastools", not 28 "Lastools version 1.0.1 64-bit") and localised. 29 """ 30 return self.tr('Your plugin') 31 32 def icon(self) -> QIcon: 33 """Should return a QIcon which is used for your provider inside 34 the Processing toolbox. 35 """ 36 return QgsProcessingProvider.icon(self)
example_processing_algorithm.pywhich contains the example algorithm file. Copy/paste the content of the script template file and update it according to your needs.
You should have a tree similar to this:
1└── your_plugin_root_folder 2 ├── __init__.py 3 ├── LICENSE 4 ├── metadata.txt 5 └── processing_provider 6 ├── example_processing_algorithm.py 7 ├── __init__.py 8 └── provider.py
Now you can reload your plugin in QGIS and you should see your example script in the Processing toolbox and modeler.
17.3. Implementing custom Processing algorithms
17.3.1. Creating a custom algorithm
Here’s a simple example of a custom buffer algorithm:
1from qgis.core import (
2 QgsProcessingAlgorithm,
3 QgsProcessingParameterFeatureSource,
4 QgsProcessingParameterNumber,
5 QgsProcessingParameterFeatureSink,
6 QgsFeatureSink,
7)
8
9class BufferAlgorithm(QgsProcessingAlgorithm):
10
11 INPUT = 'INPUT'
12 DISTANCE = 'DISTANCE'
13 OUTPUT = 'OUTPUT'
14
15 def initAlgorithm(self, config=None):
16 self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, 'Input layer'))
17 self.addParameter(QgsProcessingParameterNumber(self.DISTANCE, 'Buffer distance', defaultValue=100.0))
18 self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, 'Output layer'))
19
20 def processAlgorithm(self, parameters, context, feedback):
21 source = self.parameterAsSource(parameters, self.INPUT, context)
22 distance = self.parameterAsDouble(parameters, self.DISTANCE, context)
23 (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
24 source.fields(), source.wkbType(), source.sourceCrs())
25
26 for f in source.getFeatures():
27 f.setGeometry(f.geometry().buffer(distance, 5))
28 sink.addFeature(f, QgsFeatureSink.FastInsert)
29
30 return {self.OUTPUT: dest_id}
31
32 def name(self):
33 return 'buffer'
34
35 def displayName(self):
36 return 'Buffer Features'
37
38 def group(self):
39 return 'Examples'
40
41 def groupId(self):
42 return 'examples'
43
44 def createInstance(self):
45 return BufferAlgorithm()
17.3.2. Customizing the algorithm dialog
Custom dialogs are especially useful when working with nested or dynamic inputs,
when parameters depend on external data sources such as APIs (e.g. dynamically populated dropdowns),
or when you need advanced validation and custom layout behavior that isn’t supported by the default Processing dialog.
To override the default UI (e.g. for complex parameter types or dynamic logic),
subclass QgsProcessingAlgorithmDialogBase.
To render your custom UI in the standard Processing dialog window, you must call self.setMainWidget(panel),
where panel is a QgsPanelWidget containing your custom layout.
This ensures your interface is correctly displayed and interacts properly with the Processing framework.
Here is an example that integrates signal management using QTimer for debounced input:
1from qgis.PyQt.QtCore import Qt, QT_VERSION_STR, QTimer
2from qgis.core import (
3 QgsProcessingAlgorithm,
4 QgsProcessingContext,
5 QgsProcessingFeedback,
6 Qgis,
7)
8from qgis.PyQt.QtWidgets import QWidget, QVBoxLayout, QLineEdit
9from qgis import gui, processing
10from datetime import datetime
11from typing import Dict, Optional
12from osgeo import gdal
13
14class CustomAlgorithmDialog(gui.QgsProcessingAlgorithmDialogBase):
15 def __init__(
16 self,
17 algorithm: QgsProcessingAlgorithm,
18 parent: Optional[QWidget] = None,
19 title: Optional[str] = None,
20 ):
21 super().__init__(
22 parent,
23 flags=Qt.WindowFlags(),
24 mode=gui.QgsProcessingAlgorithmDialogBase.DialogMode.Single,
25 )
26 self.context = QgsProcessingContext()
27 self.setAlgorithm(algorithm)
28 self.setModal(True)
29 self.setWindowTitle(title or algorithm.displayName())
30
31 self.panel = gui.QgsPanelWidget()
32 layout = self.buildDialog()
33 self.panel.setLayout(layout)
34 self.setMainWidget(self.panel)
35
36 self.cancelButton().clicked.connect(self.reject)
37
38 def buildDialog(self) -> QVBoxLayout:
39 layout = QVBoxLayout()
40
41 self.input = QLineEdit()
42
43 # Set up a debounced signal using QTimer
44 self._update_timer = QTimer(self, singleShot=True)
45 self._update_timer.timeout.connect(self._on_collection_id_ready)
46 self.input.textChanged.connect(self._on_collection_id_changed)
47
48 layout.addWidget(self.input)
49
50 return layout
51
52 def _on_collection_id_changed(self):
53 self._update_timer.start(500) # Debounce input
54
55 def _on_collection_id_ready(self):
56 self.pushInfo("Fetching metadata for collection ID…")
57
58 def getParameters(self) -> Dict:
59 try:
60 return {'DISTANCE': float(self.input.text())}
61 except ValueError:
62 raise ValueError("Invalid buffer distance")
63
64 def processingContext(self):
65 return self.context
66
67 def createFeedback(self):
68 return QgsProcessingFeedback()
69
70 def runAlgorithm(self):
71 context = self.processingContext()
72 feedback = self.createFeedback()
73 params = self.getParameters()
74
75 self.pushDebugInfo(f"QGIS version: {Qgis.QGIS_VERSION}")
76 self.pushDebugInfo(f"QGIS code revision: {Qgis.QGIS_DEV_VERSION}")
77 self.pushDebugInfo(f"Qt version: {QT_VERSION_STR}")
78 self.pushDebugInfo(f"GDAL version: {gdal.VersionInfo('--version')}")
79 self.pushCommandInfo(f"Algorithm started at: {datetime.now().isoformat(timespec='seconds')}")
80 self.pushCommandInfo(f"Algorithm '{self.algorithm().displayName()}' starting…")
81 self.pushCommandInfo("Input parameters:")
82 for k, v in params.items():
83 self.pushCommandInfo(f" {k}: {v}")
84
85 results = processing.run(self.algorithm(), params, context=context, feedback=feedback)
86 self.setResults(results)
87 self.showLog()
To launch the custom dialog for a given algorithm, simply instantiate
CustomAlgorithmDialog with your algorithm instance and call exec():
dlg = CustomAlgorithmDialog(BufferAlgorithm())
dlg.exec()
17.3.3. Managing Qt Signals
When building reactive dialogs, manage signal connections carefully.
The above pattern uses a QTimer to debounce input from the text field, preventing rapid repeated calls.
This is especially useful when fetching metadata or updating UI elements based on user input.
Always connect signals once (typically in __init__) and use singleShot=True
to ensure the slot is triggered only once after a delay.