Comment implémenter le multithreading PyQGIS pour mettre à jour une barre de progression

9

Je développe un plugin PyQGIS en utilisant python. Je fais face à un problème lors de l'implémentation du filetage dans mon plugin. J'ai écrit un script Python qui contient une classe encapsulant toutes les méthodes de géotraitement utilisées. Le problème auquel je suis confronté est le traitement des méthodes dans les threads. Pour donner une meilleure image de mon problème, j'ai une interface utilisateur qui appelle la méthode calcNDVI()comme:

self.lst.calcNDVI(self.RedBand, self.NIRBand, None, self.outputRaster, self.sensorType, self.dataType, self.addToQGIS)

Cet appel de fonction, appelle une méthode calcNDVI () qui fait toute la magie et ajoute le résultat à un projet QGIS. L'appel de méthode est également associé à la transmission de certains arguments.

J'ai parcouru de nombreuses sources mais je n'arrive pas à comprendre comment je peux implémenter mes algorithmes de manière filetée. Le code que j'ai rencontré implémente tout dans la méthode d'exécution, ce qui me rend la tâche difficile car j'ai plus d'une méthode à traiter dans ma classe, et j'aimerais également que l'utilisateur puisse choisir la méthode à exécuter l'interface utilisateur.

Je traite des ensembles de données Landsat qui prennent trop de temps à traiter.

Milton Isaya
la source

Réponses:

1

Tout d'abord, implémentez tous vos calculs lourds dans une sous-classe QRunnable. Jetez un œil ici pour obtenir plus de détails ( http://pyqt.sourceforge.net/Docs/PyQt4/qrunnable.html ). Après cela, dans votre bouton ok (ou dans la méthode qui lancera le processus), vous pouvez faire quelque chose comme ceci:

    # Initiating processing
    task = ThreadTask(init parameters...)
    task.setParameters( your parameters here...)
    # Connect your signal here (somethig like this)
    task.signals.processFinished.connect(self.processFinished)
    task.signals.errorOccurred.connect(self.errorOccurred)
    task.signals.userCanceled.connect(self.userCanceled)
    # Setting the progress bar
    self.progressMessageBar = self.iface.messageBar().createMessage('Processing landsat image...')
    self.progressBar = QtGui.QProgressBar()
    self.progressBar.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
    self.progressMessageBar.layout().addWidget(self.progressBar)
    self.iface.messageBar().pushWidget(self.progressMessageBar, self.iface.messageBar().INFO)
    self.progressBar.setRange(0, 0)
    self.progressMessageBar.destroyed.connect(task.signals.cancel)
    # Starting process
    self.threadpool.start(task)

N'oubliez pas de créer un objet QThreadPool pour démarrer votre thread:

self.threadpool = QThreadPool()
lcoandrade
la source