TransWikia.com

Opening plot window from PyQGIS processing script

Geographic Information Systems Asked by Andre Geo on January 30, 2021

I have this script which creates an elevation profile with annotated points in a matplotlib.pyplot window.

It works perfectly in the console, but I want to add it to the QGIS toolbox so it can be run without opening the python console and editor (and so additional files/layers can be selected before running).

The algorithm is just the code wrapped in QGIS’s QgsProcessingAlgorithm class.
Running it crashes QGIS and I’m pretty sure it hangs at .show().

PyQt5 example plot that works

import sys
import matplotlib
matplotlib.use('Qt5Agg')

from PyQt5 import QtCore, QtGui, QtWidgets

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure

class MplCanvas(FigureCanvasQTAgg):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        sc = MplCanvas(self, width=5, height=4, dpi=100)
        sc.axes.plot([0,1,2,3,4], [10,1,20,3,40])

        # Create toolbar, passing canvas as first parament, parent (self, the MainWindow) as second.
        toolbar = NavigationToolbar(sc, self)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(toolbar)
        layout.addWidget(sc)

        widget = QtWidgets.QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        self.show()
        print('[end of main window]')

app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()
print('[FINISHED]')

processing script that doesn’t

from qgis.core import (
    QgsProcessing,
    QgsProcessingAlgorithm,
    QgsProcessingMultiStepFeedback,
    QgsProcessingParameterFile,
    QgsProcessingParameterVectorLayer,
    QgsProject,
    QgsPoint)
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('Qt5Agg')
from PyQt5 import (QtCore, 
    QtGui, 
    QtWidgets)
from matplotlib.backends.backend_qt5agg import (
    FigureCanvasQTAgg, 
    NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
import os
import sys
import processing

class MplCanvas(FigureCanvasQTAgg):

    def __init__(self, parent=None, width=18, height=5, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__()#*args, **kwargs)

        sc = MplCanvas(self, width=5, height=4, dpi=100)
        sc.axes.plot([0,1,2,3,4], [10,1,20,3,40])

        toolbar = NavigationToolbar(sc, self)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(toolbar)
        layout.addWidget(sc)

        widget = QtWidgets.QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        self.show()
        print('[FINISHED]')

class PlotProfileAKO(QgsProcessingAlgorithm):

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFile('DrillingProgram', 'Drilling Program', behavior=QgsProcessingParameterFile.File, fileFilter='All Files (*.*)', defaultValue=None))

    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
        results = {}
        outputs = {}
        
        w = MainWindow()
        QtWidgets.QApplication(sys.argv)
        
        feedback.setCurrentStep(1)
        if feedback.isCanceled():
            return {}

        return {}

    def name(self):
        return 'Plot Profile AKO test 1'

    def displayName(self):
        return 'Plot Profile AKO test 1'

    def group(self):
        return ''

    def groupId(self):
        return ''

    def createInstance(self):
        return PlotProfileAKO()

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP