أفضل ممارسات Qt QML

مع مواصلة تطوير التطبيقات، ينبغي عليك معرفة بعض التفاصيل التي يمكنها تنفيذ التطبيقات على نحو أفضل وتواجه مشاكل طفيفة. يناقش هذا الموضوع تفاصيل هامة ينبغي عليك وضعها في الاعتبار.

عرض الخريطة

يوفر ArcGIS Runtime SDK for Qt ثلاثة أنماط لعرض خريطة في عرض الخريطة. في AppStudio، ستكتب التطبيق في QML، لذا ستستخدم نوع الخريطة MapView.

تتيح لك واجهة برمجة التطبيقات (API) QML من شركة Qt كتابة تطبيقات عبر الأنظمة الأساسية باستخدام QML، وهي عبارة عن بناء جملة تعريفي سهل القراءة للغاية لتصميم وإنشاء واجهات مستخدم تفاعلية وسلسة لتطبيقات سطح المكتب والهاتف المحمول الأصلية. يقوم ArcGIS Runtime SDK for Qt بتوسعة QML مع أنواع QML التي توفر وظيفة ArcGIS Runtime. يتم التصريح عن الكائنات بشكل تسلسلي هرمي ولها خصائص قابلة للربط لتوفير سلوك ديناميكي تلقائيًا. تُستخدم وظائف JavaScript لتوفير التعليمات البرمجية الإجرائية عند الضرورة. تُعد هذه ميزة مهمة للمطورين الذين لديهم خلفية عن تطوير الويب ويرغبون في تطوير تطبيقات أصلية.

أعلن عن Rectangle الذي يحتوي على MapView. في MapView، أعلن عن Map للعرض و Viewpoint أولي.

Rectangle {
    width: 800
    height: 600
     property real scaleFactor: System.displayScaleFactor
     // Map view UI presentation at top
    MapView {
        id: mv
         anchors.fill: parent
        wrapAroundMode: Enums.WrapAroundModeDisabled
         Map {
            BasemapTopographic {}
            initialViewpoint: viewPoint
             FeatureLayer {
                id: featureLayer
                 ServiceFeatureTable {
                    id: featureTable
                    url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/SF311/FeatureServer/0"
                }
            }
        }
         ViewpointCenter {
            id: viewPoint
            center: Point {
                x: -13630484
                y: 4545415
                spatialReference: SpatialReference {
                    wkid: 102100
                }
            }
            targetScale: 300000
        }
    }

المتغيرات ذات النوع القوي

عند الإعلان عن الخصائص في QML، يكون من السهل والملائم استخدام نوع المتغير العام var، ومع ذلك، فمن الأفضل دائمًا استخدام المتغيرات ذات النوع القوي. يوضح المتغير ذو النوع القوي بشكل صريح نوع البيانات التي يمكن تخزينها في المتغير، على سبيل المثال، عدد صحيح أو سلسلة أو قيمة عشرية. قد تمنع المتغيرات ذات النوع القوي تعيين قيم خاطئة، وتُعد أسهل في القراءة، وأسهل في تصحيح أخطاء المتغيرات المقارنة من النوع var. لن يمنع المتغير ذو النوع var تعيين قيمة عشرية له، حتى إذا كان من المفترض أن تحتوي القيمة فقط على أعداد صحيحة.

في المثال التالي، يتم في البداية تعيين قيمة 10 لمتغير العدد الصحيح intValue. لاحقًا في التعليمة البرمجية، يتم تحديث المتغير نفسه بقيمة سلسلة.

property int intValue = 10
...
intValue = "A string value"

عند تشغيل هذه التعليمة البرمجية، سيظهر خطأ في وحدة التحكم يشير صراحةً إلى رقم السطر حيث تم تعيين قيمة السلسلة، ويذكر ما يلي، خطأ: لا يمكن تعيين QString إلى int، مما يسهل استكشاف الخطأ في التعليمة البرمجية وإصلاحه.

إذا تم تعيين قيمة ذات نوع خاطئ لمتغير من النوع var، فلن يتم الإبلاغ عن خطأ.

واجهات مستخدم قابلة للتحجيم

عند تصميم واجهة المستخدم في تطبيقك، من المهم مراعاة النطاق المتطور باستمرار لأحجام الشاشات ودرجات الدقة التي يمكن استخدام تطبيقك عليها. يمكن تحقيق ذلك من خلال تضمين الأيقونات والأزرار والخلفيات لكل دقة شاشة، أو باستخدام رسومات بيانات خطية قابلة للتحجيم (SVG).

عند تضمين مجموعة من الصور بدقة مختلفة، اختر اصطلاحًا لتسمية الملفات يميز بوضوح أحجام الصور. على سبيل المثال: تمثل image-name1x.png وimage-name1.5x.png وimage-name2x.png الصور التي يكون حجمها 1 مضروبًا في نقطة لكل بوصة أساسية و1.5 مضروبًا في نقطة لكل بوصة أساسية و3 مضروبًا في نقطة لكل بوصة أساسية.

تُعد ملفات SVG مثالية للصور الصغيرة، التي تكون أيقونات عادةً. قد تكون ملفات SVG الكبيرة بطيئة في العرض، لذا ضع في اعتبارك استخدام الصور للخلفيات.

للحصول على مزيد من المعلومات، راجع واجهات المستخدم القابلة للتحجيم من Qt.

تكوين تطبيقك

يتم بناء AppStudio أعلى Qt Framework، وهو ما يعني إمكانية وصولك إلى كل أدوات التصحيح نفسها المستخدمة مع Qt. فيما يلي بعض النصائح والتلميحات المفيدة لتصحيح أخطاء تطبيقات Qt الخاصة بك.

استخدام وكيل ويب

عند تصحيح أخطاء تطبيقات AppStudio، غالبًا ما تكون أداة تصحيح الويب مفيدة لالتقاط طلبات HTTP المرسلة وتحليلها والاستجابات المعادة. Fiddler وCharles مثالان على أدوات تصحيح أخطاء الويب المستخدمة لأداء هذه المهمة. يمكنك استخدام هذه الأدوات لتصحيح أخطاء التطبيق بإضافة تعليمة C++ البرمجية إلى تطبيقك: QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, "127.0.0.1", 8888));. يمكن تعيين هذه التعليمة البرمجية في وقت التشغيل، ويمكن إما أن تكون في main.cpp أو في تصنيف C++ آخر. بالإضافة إلى استخدام وكيل لتصحيح الأخطاء، يمكن أيضًا استخدام QNetworkProxy::setApplicationProxy() لتحديد خادم الوكيل لمؤسستك. للقيام بذلك، حدد عنوان URL ومنفذ خادم وكيل المؤسسة. يمكن العثور على المزيد من المعلومات في AppFramework وثائق NetworkProxy.

باستخدام JSON.stringify()

عند استخدام طريقة JSON.stringify()، تجنب التمرير في مرجع الكائن ذاته. استخدم خاصية json الخاصة بالكائن في صورة وسيطة، على سبيل المثال: JSON.stringify(graphic.geometry.json)

نموذج ذاكرة واجهة برمجة تطبيق QML

نموذج الذاكرة المستخدم لتطبيقات QML يستند إلى تجميع البيانات المهملة. سيتم مسح المتغيرات غير المشار إليها عن طريق مُجمع البيانات المهملة لـ QML Engine. وبناءً عليه، يجب الإشارة صراحةً إلى جميع الكائنات لتجنب تجميع البيانات المهملة عند تزال قيد الاستخدام.

إنشاء كائن باستخدام JavaScript

تعمل طريقة ArccGISRuntimeEnvironment.createObject() على إنشاء مثيلات جديدة لكائن ما وترجعها من خلال مشغل QML. يُحدد عمر هذه المثيلات بواسطة الكائن الأصل للمثيل. عندما يجمع الأصل البيانات المهملة، سيكون الأمر كذلك للمثيلات الفرعية. توجد طرق مختلفة لاستمرار مثيل تم إنشاؤه باستخدام ArccGISRuntimeEnvironment.createObject()، بما في ذلك الطرق التالية:

  • يمكنك تحديد الكائن الأصل في معلمة ArccGISRuntimeEnvironment.createObject() الاختيارية الثالثة.
  • في تعليمة QML البرمجية التعريفية، قم بتعريف الكائن كخاصية لكائن آخر. ثم في تعليمة JavaScript البرمجية، أنشيء مثيل الكائن باستخدام ArccGISRuntimeEnvironment.createObject(). يصبح التصنيف الذي يحتوي على الخاصية أصل المثيل الجديد. احرص على إعلان الخاصية على أنها من نفس نوع ArcGIS Runtime QML أثناء إنشاء مثيل له.

إذا لم تحدد الأصل، فسيتم تعيين JavaScript كأصل مثيل الكائن. يتتبع QML المثيل ويحذفه عند عدم وجود مراجع JavaScript متبقية للمثيل (أي عندما يخرج المثيل عن النطاق.)

تتضمن بعض أنواع ArcGIS Runtime QML طريقة clone() المستخدمة لإنشاء مثيل كائن جديد لذلك النوع. عند استخدام clone() لإنشاء مثيل، سيكون JavaScript هو الأصل. يمكنك تغيير الأصل باستخدام خاصية parent.

العمل مع النماذج

تصل النماذج إلى مثيلات الكائن بشكل صريح. عند العمل مع النماذج، من الضروري توفير بيانات مستمرة للنموذج المراد الوصول إليه. لا يعد وضع مثيلات الكائن التي تم إنشاؤها حديثًا في QML ListModel مباشرةً كافيًا للحفاظ على عمر تلك المثيلات لأن القيام بذلك لا يشير إلى حساب تلك المثيلات. (راجع القسم السابق حول إنشاء الكائنات باستخدام JavaScript.) تتمثل إحدى طرق تجنب جمع البيانات المهملة في إنشاء خاصية تمثل قائمة، وإضافة المثيلات إلى القائمة المستمرة. العمر الافتراضي لخاصية القائمة هو ذلك الخاص بالأصل.

// In a QML declaration:
ListModel {
  id: myListModel
  property var geoms: []
}

//...
// In a JavaScript function:
var newPoint = point.clone();

// avoid the following, because newPoint is not reference counted 
// myListModel.append(
//    {"geometry", newPoint
//    });  

// do this instead to give newPoint the same lifetime as myListModel
myListModel.geoms.push(newPoint);

ينطبق هذا المفهوم أيضًا على قائمة مثيلات الكائن بناءً على QQmlListProperty. على الرغم من أنه يمكنك تعيين مثل هذه القائمة مباشرة كإدخال للنموذج، يجب عليك تجنب القيام بذلك. سيقوم النموذج بإنشاء مراجع غير صريحة لعناصر القائمة وبالتالي سيتم جمع العناصر غير المرغوب فيها. للحصول على النتائج الصحيحة، عليك أولاً بتعيين جميع عناصر القائمة إلى قائمة محلية. سوف تستمر هذه المراجع الصريحة وتتجنب تجميع البيانات المهملة مبكرًا. يعمل المثال التالي على إنشاء مكون list ويُدرج جميع الحقول من جدول المعلم. ثم يقوم بتعيين القائمة كنموذج ComboBox.

GeodatabaseFeatureTable {
    id: featureTable
}

ComboBox {
    id: comboBox
//    model: featureTable.fields // avoid this, because the model will create non-explicit references
    textRole: "name"
}

property var fieldList: []

function initFieldListModel() {
    for (var i = 0; i < featureTable.fields.length; ++i) {
        fieldList.push(featureTable.fields[i]);
    }
    comboBox.model = fieldList;
}

تفرد الكائن

لا يوجد ضمان يمكنك من خلاله الحصول على نفس الكائن مرة أخرى حتى لنفس المحصل أو استدعاء الوظيفة. على هذا النحو، يجب تجنب مقارنة الكائن المباشر، على سبيل المثال:

Map { id: map }
...
var viewpoint = map.initialViewpoint;
// Avoid comparisons like the following code.
// Although the objects' contents are identical, 
// the objects may be different objects.
if (viewpoint === map.initialViewpoint)

الخصائص المخصصة بأنواع QML

إن الخاصية المخصصة (المعرفة من قبل المستخدم) هي الخاصية التي تضيفها إلى مثيل من نوع QML عند تعريفه. ولا تمثل الخاصية جزءًا من النوع ولكنها موجودة كخاصية مخصصة في المثيل المحدد. تتيح لك لغة QML إضافة خصائص مخصصة إلى المثيلات عندما تعريفها. بينما يمكنك إضافة خصائص مخصصة إلى مثيلات نوع ArcGIS Runtime QML، فقد لا يتم الاحتفاظ بهذه الخاصية في جميع الحالات بسبب الطريقة التي يتم بها الحفاظ على المثيلات داخل واجهة برمجة التطبيق. لذلك، تجنب استخدام الخصائص المخصصة في مثيلات الأنواع التي لا تدعمها.

تدعم أنواع QML التالية والأنواع المشتقة من هذه الأنواع، الخصائص المخصصة. بينما لا تقدم أنواع ArcGIS Runtime QML الأخرى الدعم.

  • ArcGISMapServiceInfo
  • خريطة الأساس
  • بيانات الاعتماد
  • FeatureTable
  • قاعدة البيانات الجغرافية
  • GraphicsOverlay
  • LayerContent
  • خريطة
  • بوابة إلكترونية
  • PortalTask
  • VectorTileSourceInfo

العمل باستخدام JSON

ترث العديد من أنواع QML من JsonSerializable، مما يتيح لك إجراء تسلسل للنوع أو ملء محتوياته في JSON. عند إنشاء كائن من JSON، أنشئ مثيلاً أولاً، ثم مرر هذا المثيل في صورة إدخال إلى الطريقة.

تُنشئ تعليمة JavaScript البرمجية هذا وتملأ PictureMarkerSymbol من JSON وتستخدمه في رسومات جديدة.

Graphic {
  id: myGraphic


  property var pmsJson: {"type": "esriPMS", "url": "http://myurl.com/folder/my-icon.png","width": 60,"height": 60, "angle":20}


  Component.onCompleted: {
    var pmsFromJson = ArcGISRuntimeEnvironment.createObject("PictureMarkerSymbol", {json: pmsJson});
    pmsFromJson.errorChanged.connect(function(error){ verify(false, error.message + " (" + error.additionalMessage + ")"); });
    myGraphic.symbol = pmsFromJson;
  }
}

التعامل مع السلاسل المترجمة

يجب أن تستخدم جميع السلاسل التي يتم عرضها في واجهة المستخدم الخاصة بالتطبيق تنسيق qsTr() لضمان إمكانية تعميم تطبيقك.

من المهم أيضًا مراعاة السلاسل المترجمة عند تحديد منطق التطبيق الخاص بك. إذا كان المستخدم سيحدد خيارًا بناءً على السلاسل في واجهة المستخدم، على سبيل المثال تحديد من القائمة المنسدلة، يجب أن تستخدم كل حالة داخل جملة التبديل السلسلة المترجمة.

في المثال التالي، ستظهر لوحة نبذة عن عند تحديد عنصر القائمة نبذة عن، بغض النظر عن اللغة التي يعرضها التطبيق:

case qsTr("About"):
    pageView.hideSearchItem()
    panelDockItem.addDock("aboutPanel")
    break

OpenGL أو ANGLE يعرضان على Windows

يتضمن Qt محركين مختلفين للعرض لنظام Windows الأساسي: OpenGL وDirectX عبر ANGLE. بشكل افتراضي، سيحاول Qt العرض باستخدام OpenGL. إذا لم تكن برامج التشغيل المناسبة متاحة، فسوف تعود إلى استخدام ANGLE من أجل العرض. الإصدارات السابقة من ArcGIS Runtime تدعم ANGLE فقط. بدءًا من ArcGIS Runtime 100.3.0، يمكن أن تدعم تطبيقاتك كلاً من OpenGL وANGLE بشكل كامل كي يمكنك الاستفادة من محرك العرض وآلية Qt الاحتياطية عندما يتعذر استخدام OpenGL على نظام معين. لمزيد من المعلومات، راجع وثائق Qt.

للاختيار بين عرض OpenGL وANGLE بشكل افتراضي، استخدم خيارات الإعدادات > الأنظمة الأساسية > Windows > محرك عرض الرسوم في AppStudio. لا حاجة إلى أي تغييرات للتعليمات البرمجية.