13. Communiquer avec l’utilisateur
Indication
Les extraits de code sur cette page nécessitent les importations suivantes si vous êtes en dehors de la console pyqgis :
1from qgis.core import (
2 QgsMessageLog,
3 QgsGeometry,
4)
5
6from qgis.gui import (
7 QgsMessageBar,
8)
9
10from qgis.PyQt.QtWidgets import (
11 QSizePolicy,
12 QPushButton,
13 QDialog,
14 QGridLayout,
15 QDialogButtonBox,
16)
Cette section montre quelques méthodes et éléments qui devraient être employés pour communiquer avec l’utilisateur dans l’objectif de conserver une certaine constance dans l’interface utilisateur
13.1. Afficher des messages. La classe QgsMessageBar
Utiliser des boîtes à message est généralement une mauvaise idée du point de vue de l’expérience utilisateur. Pour afficher une information simple sur une seule ligne ou des messages d’avertissement ou d’erreur, la barre de message QGIS est généralement une meilleure option.
En utilisant la référence vers l’objet d’interface QGis, vous pouvez afficher un message dans la barre de message à l’aide du code suivant
from qgis.core import Qgis
iface.messageBar().pushMessage("Error", "I'm sorry Dave, I'm afraid I can't do that", level=Qgis.Critical)
Messages(2): Error : I'm sorry Dave, I'm afraid I can't do that
Vous pouvez spécifier une durée pour que l’affichage soit limité dans le temps.
iface.messageBar().pushMessage("Ooops", "The plugin is not working as it should", level=Qgis.Critical, duration=3)
Messages(2): Ooops : The plugin is not working as it should
Les exemples ci-dessus montrent une barre d’erreur, mais le paramètre level
peut être utilisé pour créer des messages d’avertissement ou des messages d’information, en utilisant l’énumération Qgis.MessageLevel
. Vous pouvez utiliser jusqu’à 4 niveaux différents :
Info
Warning
Critical
Success
Des Widgets peuvent être ajoutés à la barre de message comme par exemple un bouton pour montrer davantage d’information
1def showError():
2 pass
3
4widget = iface.messageBar().createMessage("Missing Layers", "Show Me")
5button = QPushButton(widget)
6button.setText("Show Me")
7button.pressed.connect(showError)
8widget.layout().addWidget(button)
9iface.messageBar().pushWidget(widget, Qgis.Warning)
Messages(1): Missing Layers : Show Me
Vous pouvez également utiliser une barre de message au sein de votre propre boîte de dialogue afin de ne pas afficher de boîte à message ou bien s’il n’y pas d’intérêt de l’afficher dans la fenêtre principale de QGis
1class MyDialog(QDialog):
2 def __init__(self):
3 QDialog.__init__(self)
4 self.bar = QgsMessageBar()
5 self.bar.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Fixed )
6 self.setLayout(QGridLayout())
7 self.layout().setContentsMargins(0, 0, 0, 0)
8 self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok)
9 self.buttonbox.accepted.connect(self.run)
10 self.layout().addWidget(self.buttonbox, 0, 0, 2, 1)
11 self.layout().addWidget(self.bar, 0, 0, 1, 1)
12 def run(self):
13 self.bar.pushMessage("Hello", "World", level=Qgis.Info)
14
15myDlg = MyDialog()
16myDlg.show()
13.2. Afficher la progression
Les barres de progression peuvent également être insérées dans la barre de message QGis car, comme nous l’avons déjà vu, cette dernière accepte les widgets. Voici un exemple que vous pouvez utilisez dans la console.
1import time
2from qgis.PyQt.QtWidgets import QProgressBar
3from qgis.PyQt.QtCore import *
4progressMessageBar = iface.messageBar().createMessage("Doing something boring...")
5progress = QProgressBar()
6progress.setMaximum(10)
7progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
8progressMessageBar.layout().addWidget(progress)
9iface.messageBar().pushWidget(progressMessageBar, Qgis.Info)
10
11for i in range(10):
12 time.sleep(1)
13 progress.setValue(i + 1)
14
15iface.messageBar().clearWidgets()
Messages(0): Doing something boring...
Vous pouvez également utiliser la barre d’état intégrée pour signaler les progrès, comme dans l’exemple suivant :
1vlayer = iface.activeLayer()
2
3count = vlayer.featureCount()
4features = vlayer.getFeatures()
5
6for i, feature in enumerate(features):
7 # do something time-consuming here
8 print('.') # printing should give enough time to present the progress
9
10 percent = i / float(count) * 100
11 # iface.mainWindow().statusBar().showMessage("Processed {} %".format(int(percent)))
12 iface.statusBarIface().showMessage("Processed {} %".format(int(percent)))
13
14iface.statusBarIface().clearMessage()
13.3. Journal
Trois types de journalisation sont disponibles dans QGIS pour enregistrer et sauvegarder toutes les informations relatives à l’exécution de votre code. Chacun a son emplacement de sortie spécifique. Veuillez utiliser la méthode de journalisation qui convient le mieux à votre situation :
QgsMessageLog
est destiné aux messages pour communiquer des problèmes à l’utilisateur. La sortie du QgsMessageLog est affichée dans le panneau des messages de log.Le module python intégré logging est destiné au débogage au niveau de l’API Python QGIS (PyQGIS). Il est recommandé aux développeurs de scripts Python qui ont besoin de déboguer leur code python, par exemple les identifiants d’entités ou les géométries
QgsLogger
est destiné aux messages pour le débogage / les développements QGIS interne (c’est-à-dire que vous soupçonnez que quelque chose est déclenché par un code défectueux). Les messages ne sont visibles qu’avec les versions de QGIS destinées aux développeurs.
Des exemples pour les différents types d’exploitation forestière sont présentés dans les sections suivantes.
Avertissement
L’utilisation de l’instruction Python print
n’est pas sûre dans tout code qui peut être multithreadé et ralentit extrêmement l’algorithme. Cela inclut les fonctions d’expression, les renderers, les couches de symboles et les algorithmes de traitement (entre autres). Dans ces cas, vous devriez toujours utiliser le module python logging ou les classes thread safe (QgsLogger
ou QgsMessageLog
) à la place.
13.3.1. QgsMessageLog
# You can optionally pass a 'tag' and a 'level' parameters
QgsMessageLog.logMessage("Your plugin code has been executed correctly", 'MyPlugin', level=Qgis.Info)
QgsMessageLog.logMessage("Your plugin code might have some problems", level=Qgis.Warning)
QgsMessageLog.logMessage("Your plugin code has crashed!", level=Qgis.Critical)
MyPlugin(0): Your plugin code has been executed correctly
(1): Your plugin code might have some problems
(2): Your plugin code has crashed!
Note
Vous pouvez voir la sortie du QgsMessageLog
dans Journal des messages (log).
13.3.2. Le python intégré dans le module de journalisation
1import logging
2formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
3logfilename=r'c:\temp\example.log'
4logging.basicConfig(filename=logfilename, level=logging.DEBUG, format=formatter)
5logging.info("This logging info text goes into the file")
6logging.debug("This logging debug text goes into the file as well")
La méthode basicConfig permet de configurer la configuration de base de l’enregistrement. Dans le code ci-dessus, le nom de fichier, le niveau de journalisation et le format sont définis. Le nom du fichier fait référence à l’endroit où écrire le fichier journal, le niveau de journalisation définit les niveaux de sortie et le format définit le format dans lequel chaque message est sorti.
2020-10-08 13:14:42,998 - root - INFO - This logging text goes into the file
2020-10-08 13:14:42,998 - root - DEBUG - This logging debug text goes into the file as well
Si vous voulez effacer le fichier journal chaque fois que vous exécutez votre script, vous pouvez faire quelque chose comme
if os.path.isfile(logfilename):
with open(logfilename, 'w') as file:
pass
D’autres ressources sur la façon d’utiliser le système d’exploitation forestière python sont disponibles à l’adresse suivante
Avertissement
Veuillez noter que sans enregistrement dans un fichier en définissant un nom de fichier, l’enregistrement peut être multithreadé, ce qui ralentit fortement la sortie.