13. 사용자에게 정보 전달하기
힌트
여러분이 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)
이 장에서는 사용자 인터페이스에서 일관성을 유지하기 위해 이용해야 하는 몇몇 메소드 및 요소들에 대해 설명합니다.
13.1. Showing messages. The QgsMessageBar class
메시지 상자를 이용하는 것은 사용자 경험이라는 관점에서 그리 좋은 생각이 아닙니다. 짧은 정보 또는 경고/오류 메시지를 표출하는 데에는 QGIS 메시지 바를 이용하는 편이 더 낫습니다.
QGIS 인터페이스 오브젝트의 참조(reference)를 사용하면, 다음 코드를 통해 메시지 바에 메시지를 표시할 수 있습니다.
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
지속 시간(duration
)을 설정해서 제한된 시간 동안 메시지를 표출할 수 있습니다.
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
The examples above show an error bar, but the level
parameter can be used
to creating warning messages or info messages, using the
Qgis.MessageLevel
enumeration. You can use up to 4 different levels:
Info
Warning
Critical
Success
추가적인 정보 표시를 위한 버튼 등의 위젯을 메시지 바에 추가할 수도 있습니다.
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
별도의 메시지 상자가 필요 없거나 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. 진행률 표시
앞에서 배웠듯이 QGIS 메시지 바에 위젯을 추가할 수 있으므로, 진행률(progress) 막대도 추가할 수 있습니다. 다음은 여러분이 콘솔에서 실행해볼 수 있는 예시 코드입니다.
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...
Also, you can use the built-in status bar to report progress, as in the next example:
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. 로그 기록
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.
Examples for the different logging types are shown in the following sections below.
경고
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!
참고
You can see the output of the QgsMessageLog
in the 로그 메시지 패널
13.3.2. The python built in logging module
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
If you want to erase the log file every time you execute your script you can do something like:
if os.path.isfile(logfilename):
with open(logfilename, 'w') as file:
pass
Further resources on how to use the python logging facility are available at:
경고
Please note that without logging to a file by setting a filename the logging may be multithreaded which heavily slows down the output.