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. عرض الرسائل. الصنف QgsMessageBar¶
قد يكون استخدام صناديق الرسائل فكرة سيئة من منظور تجربة المستخدم. لعرض سطر معلومات قصير أو رسائل تحذير/خطأ، يكون شريط رسائل QGIS عادةً خيارًا أفضل.
باستخدام المرجع إلى كائن واجهة QGIS، يمكنك عرض رسالة في شريط الرسائل بالشيفرة التالية
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
شكل 13.35 شريط رسائل QGIS¶
يمكنك تعيين مدة لعرضه لوقت محدود
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
شكل 13.36 شريط رسائل QGIS مع مؤقّت¶
تعرض الأمثلة أعلاه شريط خطأ، لكن يمكن استخدام المعامل level لإنشاء رسائل تحذير أو رسائل معلومات، باستخدام التعداد Qgis.MessageLevel. يمكنك استخدام ما يصل إلى 4 مستويات مختلفة:
معلومات (Info)
تحذير (Warning)
حرج (Critical)
نجاح (Success)
شكل 13.37 شريط رسائل QGIS (معلومات)¶
يمكن إضافة عناصر واجهة إلى شريط الرسائل، مثل زر لعرض مزيد من المعلومات
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
شكل 13.38 شريط رسائل QGIS مع زر¶
يمكنك حتى استخدام شريط رسائل في نافذة الحوار الخاصة بك حتى لا تضطر إلى عرض صندوق رسالة، أو إذا لم يكن من المنطقي عرضه في نافذة 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.39 شريط رسائل QGIS في نافذة حوار مخصّصة¶
13.2. عرض التقدّم¶
يمكن أيضًا وضع أشرطة التقدّم في شريط رسائل QGIS، لأنه كما رأينا يقبل عناصر الواجهة. فيما يلي مثال يمكنك تجربته في وحدة التحكم.
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...
كما يمكنك استخدام شريط الحالة المدمج للإبلاغ عن التقدّم، كما في المثال التالي:
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. التسجيل (Logging)¶
تتوفر في QGIS ثلاثة أنواع مختلفة من التسجيل لتسجيل وحفظ جميع المعلومات المتعلقة بتنفيذ شيفرتك. ولكل منها موقع مخرجات خاص به. يُرجى مراعاة استخدام طريقة التسجيل الصحيحة لغرضك:
الصنف
QgsMessageLogمخصّص للرسائل التي تُبلغ المستخدم بالمشكلات. وتُعرض مخرجات QgsMessageLog في لوحة رسائل السجل (Log Messages Panel).الوحدة المدمجة في python logging مخصّصة لتصحيح الأخطاء على مستوى QGIS Python API (PyQGIS). ويُوصى بها لمطوّري سكربتات Python الذين يحتاجون إلى تصحيح شيفرة python الخاصة بهم، مثل معرّفات المعالم أو الأشكال الهندسية
الصنف
QgsLoggerمخصّص لرسائل تصحيح الأخطاء الداخلية في QGIS / للمطوّرين (أي عندما تشتبه في أن شيئًا ما يُستدعى بسبب شيفرة معطوبة). ولا تظهر الرسائل إلا في إصدارات المطوّرين من QGIS.
تُعرض أمثلة على أنواع التسجيل المختلفة في الأقسام التالية أدناه.
تحذير
استخدام عبارة print في Python غير آمن في أي شيفرة قد تكون متعددة الخيوط، كما أنه يُبطئ الخوارزمية بشدة. ويشمل ذلك دوال التعبيرات و أدوات الرسم و طبقات الرموز و خوارزميات المعالجة (من بين أمور أخرى). في هذه الحالات يجب عليك دائمًا استخدام الوحدة logging في python أو الأصناف الآمنة للخيوط (QgsLogger أو QgsMessageLog) بدلًا منها.
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!
ملاحظة
يمكنك رؤية مخرجات QgsMessageLog في سجل لوحة الرسائل
13.3.2. وحدة التسجيل logging المدمجة في python¶
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")
تضبط الدالة basicConfig الإعداد الأساسي للتسجيل. في الشيفرة أعلاه يُعرَّف اسم الملف ومستوى التسجيل والتنسيق. يشير اسم الملف إلى المكان الذي يُكتب فيه ملف السجل، ويحدد مستوى التسجيل المستويات التي تُخرَج، ويحدد التنسيق الصيغة التي تُخرَج بها كل رسالة.
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 os.path.isfile(logfilename):
with open(logfilename, 'w') as file:
pass
تتوفر موارد إضافية حول كيفية استخدام أداة التسجيل في python على:
https://docs.python.org/3/library/logging.html (بالإنجليزية)
https://docs.python.org/3/howto/logging.html (بالإنجليزية)
https://docs.python.org/3/howto/logging-cookbook.html (بالإنجليزية)
تحذير
يُرجى ملاحظة أنه دون التسجيل إلى ملف بتعيين اسم ملف، قد يكون التسجيل متعدد الخيوط مما يُبطئ المخرجات بشدة.