Les extraits de code sur cette page nécessitent les importations suivantes si vous êtes en dehors de la console pyqgis :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from qgis.core import (
    QgsMessageLog,
    QgsGeometry,
)

from qgis.gui import (
    QgsMessageBar,
)

from qgis.PyQt.QtWidgets import (
    QSizePolicy,
    QPushButton,
    QDialog,
    QGridLayout,
    QDialogButtonBox,
)

13. Communiquer avec l’utilisateur

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
../../_images/errorbar.png

Fig. 13.25 Barre de message de QGIS

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
../../_images/errorbar-timed.png

Fig. 13.26 Barre de message de Qgis avec décompte

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 :

  1. Info

  2. Warning

  3. Critical

  4. Success

../../_images/infobar.png

Fig. 13.27 Barre de message QGis (info)

Des Widgets peuvent être ajoutés à la barre de message comme par exemple un bouton pour montrer davantage d’information

1
2
3
4
5
6
7
8
9
def showError():
    pass

widget = iface.messageBar().createMessage("Missing Layers", "Show Me")
button = QPushButton(widget)
button.setText("Show Me")
button.pressed.connect(showError)
widget.layout().addWidget(button)
iface.messageBar().pushWidget(widget, Qgis.Warning)
Messages(1): Missing Layers : Show Me
../../_images/bar-button.png

Fig. 13.28 Barre de message QGis avec un bouton

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class MyDialog(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.bar = QgsMessageBar()
        self.bar.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Fixed )
        self.setLayout(QGridLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok)
        self.buttonbox.accepted.connect(self.run)
        self.layout().addWidget(self.buttonbox, 0, 0, 2, 1)
        self.layout().addWidget(self.bar, 0, 0, 1, 1)
    def run(self):
        self.bar.pushMessage("Hello", "World", level=Qgis.Info)

myDlg = MyDialog()
myDlg.show()
../../_images/dialog-with-bar.png

Fig. 13.29 Barre de message QGis avec une boîte de dialogue personnalisée

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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import time
from qgis.PyQt.QtWidgets import QProgressBar
from qgis.PyQt.QtCore import *
progressMessageBar = iface.messageBar().createMessage("Doing something boring...")
progress = QProgressBar()
progress.setMaximum(10)
progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
progressMessageBar.layout().addWidget(progress)
iface.messageBar().pushWidget(progressMessageBar, Qgis.Info)

for i in range(10):
    time.sleep(1)
    progress.setValue(i + 1)

iface.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 :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
vlayer = iface.activeLayer()

count = vlayer.featureCount()
features = vlayer.getFeatures()

for i, feature in enumerate(features):
    # do something time-consuming here
    print('.') # printing should give enough time to present the progress

    percent = i / float(count) * 100
    # iface.mainWindow().statusBar().showMessage("Processed {} %".format(int(percent)))
    iface.statusBarIface().showMessage("Processed {} %".format(int(percent)))

iface.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

1
2
3
4
5
6
import logging
formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
logfilename=r'c:\temp\example.log'
logging.basicConfig(filename=logfilename, level=logging.DEBUG, format=formatter)
logging.info("This logging info text goes into the file")
logging.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.