13. Comunicação com o usuário
Dica
Os trechos de código desta página precisam das seguintes importações se você estiver fora do console do 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)
Esta seção mostra alguns métodos e elementos que devem ser usados para se comunicar com o usuário, a fim de manter a consistência na interface do usuário.
13.1. Mostrando mensagens. A classe QgsMessageBar
Usando caixas de mensagem pode ser uma má idéia, do ponto de vista da experiência do usuário. Para mostrar uma pequena linha de informação ou uma mensagem de aviso/erro, a barra de mensagens QGIS é geralmente uma opção melhor.
Usando a referência ao objeto de interface QGIS, você pode mostrar uma mensagem na barra de mensagem com o seguinte código
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
Você pode definir uma duração de mostrá-lo por um tempo limitado
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
Os exemplos acima mostram uma barra de erro, mas o parâmetro `` level`` pode ser usado para criar mensagens de aviso ou informações, usando enumeração Qgis.MessageLevel
. Você pode usar até 4 níveis diferentes
Info
Aviso
Crítico
Sucesso
Widgets podem ser adicionados à barra de mensagens, como por exemplo, um botão para mostrar mais informações
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
Você ainda pode usar uma barra de mensagens em sua própria caixa de diálogo para que você não tenha de mostrar uma caixa de mensagem, ou se ela não faz sentido para mostrá-la na janela principal 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. Mostrando progresso
As barras de progresso também pode ser colocado na barra de mensagem QGIS, uma vez que, como vimos, ele aceita widgets. Aqui está um exemplo que você pode tentar no 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...
Além disso, você pode usar a barra de status interna para relatar o progresso, como no próximo exemplo:
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. Carregando
There are three different types of logging available in QGIS to log and save all the information about the execution of your code. Each has its specific output location. Please consider to use the correct way of logging for your purpose:
QgsMessageLog
is for messages to communicate issues to the user. The output of the QgsMessageLog is shown in the Log Messages Panel.The python built in logging module is for debugging on the level of the QGIS Python API (PyQGIS). It is recommended for Python script developers that need to debug their python code, e.g. feature ids or geometries
QgsLogger
is for messages for QGIS internal debugging / developers (i.e. you suspect something is triggered by some broken code). Messages are only visible with developer versions of QGIS.
Exemplos para os diferentes tipos de extração são mostrados nas seguintes seções abaixo.
Aviso
Use of the Python print
statement is unsafe to do in any code which may be
multithreaded and extremely slows down the algorithm. This includes expression
functions, renderers,
symbol layers and Processing algorithms (amongst others). In these
cases you should always use the python logging module or thread safe classes
(QgsLogger
or QgsMessageLog
) instead.
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!
Nota
Você pode ver a saída da QgsMessageLog
no O painel Registo de Mensagens
13.3.2. O python construído no módulo de extração
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")
The basicConfig method configures the basic setup of the logging. In the above code the filename, logging level and the format are defined. The filename refers to where to write the logfile to, the logging level defines what levels to output and the format defines the format in which each message is output.
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
Se você quiser apagar o arquivo de log toda vez que executar seu script, você pode fazer algo como:
if os.path.isfile(logfilename):
with open(logfilename, 'w') as file:
pass
Outros recursos sobre como utilizar a instalação de extração em python estão disponíveis em:
Aviso
Please note that without logging to a file by setting a filename the logging may be multithreaded which heavily slows down the output.