اذهب إلى المحتوى

حسام برهان

الأعضاء
  • المساهمات

    215
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    31

كل منشورات العضو حسام برهان

  1. سنتحدّث في هذا المقال من سلسلة المقالات حول التعامل مع ويندوز 10 عن كيفيّة تثبيت ويندوز 10 وذلك باستخدام أسلوب التنصيب من ذاكرة USB. السبب في اختياري هذا الأسلوب هو أنّه في بعض الحالات قد تحتاج إلى تنصيب ويندوز 10 على حاسوب غير متصل بشبكة الانترنت حاليًا أو لا يحتوي على أيّ نظام تشغيل مسبقًا أو أنّه يحتوي على نظام تشغيل غير متوافق مع ويندوز. لذلك فستحتاج إلى الحصول على قرص DVD يحتوي على نسخة ويندوز 10 وقد يكون الحاسوب لا يحوي محرك أقراص مدمجة DVD عندها لابد أن تلجأ إلى أسلوب عمليّ أكثر يتمثّل في تنصيب ويندوز 10 عن طريق ملف ISO والذي سنتحدث عنه في هذا المقال. الحصول على نسخة ويندوز 10 سنقوم بتنصيب الإصدار Windows 10 Pro لذلك سنقوم بالحصول عليه من موقع مايكروسوفت. انتقل إلى هذه الصفحة التي تسمح لنا بتحميل نسخة صورة ISO من ويندوز 10. انظر إلى الشكل التالي: استخدم شريط التمرير للوصول إلى القائمة المنسدلة الخاصة بتحديد إصدار ويندوز الذي نرغب بتحميله. اختر الإصدار Windows 10 من هذه القائمة كما في الشكل التالي: بعد اختيار هذا الإصدار انقر الزر "تأكيد" لكي تظهر لك خيارات أخرى تتعلّق باللغة التي ترغب بأن يدعمها نظام التشغيل. اختر اللغة العربية ثم انقر زر "تأكيد" الذي يظهر أسفل قائمة تحديد اللغة كما في الشكل التالي: في نهاية المطاف ستزودك هذه الصفحة برابطيّ تحميل. الأوّل خاص بنسخة 32 بت، والثاني خاص بنسخة 64 بت. علمًا أنّ هذه الرّوابط تكون صالحة خلال 24 ساعة فقط. اختر نسخة 64 بت كما في الشكل التالي: ستبدأ عملية التحميل التي قد تستغرق بعض الوقت تبعًا لسرعة الاتصال لديك. علمًا أنّ حجم النسخة يقارب 3.8 جيجا بايت. نسخ ملف ISO إلى ذاكرة USB بعد الانتهاء من عمليّة التحميل ينبغي أن ننسخ ملف ISO الذي حصلنا عليه إلى ذاكرة USB. سنجعل هذه الذاكرة إقلاعية Bootable USB Flash Memory عن طريق استخدام برنامج مخصّص لهذا الغرض. وللقيام بذلك سنستخدم برنامج اسمه Rufus وهو برنامج مجانيّ ومفتوح المصدر، وسهل الاستخدام إلى حدّ كبير. يمكن الحصول على هذا البرنامج من هذا الرابط. أدرج ذاكرة USB الخاصة بك والتي يجب أن تكون سعتها 4 جيجا بايت على الأقل. ثمّ شغل برنامج Rufus الذي حصلت عليه قبل قليل. لاحظ في البداية أنّ البرنامج سيتعرّف على ذاكرة USB التي أدرجتها، ويظهرها ضمن قائمة الأجهزة Device في الأعلى كما يظهر في الشكل التالي: بالنسبة إليّ، اسم ذاكرة USB الخاصة بي: WIN10_64_AR كما يظهر من الشكل السابق. لاحظ أيضًا الزر الصغير الموجود في الأسفل والذي أحطته بمستطيل أحمر صغير. يسمح هذا الزر باختيار نسخة ملف ISO الذي نزّلناه مسبقًا وذلك لوضع هذه النسخة على ذاكرة USB. انقر هذا الزر، ومن مربّع الحوار الذي سيظهر اختر ملف ISO الذي يمثّل نسخة ويندوز 10 التي قمنا بتنزيلها، ولاحظ كيف أنّ البرنامج يتعرّف على محتوى ملف الـ ISO ويُظهر لك جميع المعلومات المتعلّقة به: اترك هذه الإعدادات كما هي بدون تعديل. يمكنك الآن نقر زر Start ليعرض لك البرنامج رسالة تحذير بأنّ محتويات ذاكرة USB سيتم محوها. بعد موافقتك على ذلك ستبدأ عملية النسخ التي ستستغرق قليلًا من الوقت. بعد الانتهاء من عملية نسخ ملف ISO إلى ذاكرة USB سيعرض لك البرنامج رسالة READY من جديد ليخبرك أنّ عملية النسخ قد انتهت، وبذلك أصبحت هذه الذاكرة جاهزة الآن لأن يتم تنصيب نظام ويندوز منها. تنصيب ويندوز 10 احرص على ضبط خيار الإقلاع من ذاكرة USB في أيّ حاسوب ترغب بتنصيب ويندوز 10 عليه، وذلك من خلال إعدادات BIOS الخاصة به. عند الإقلاع من ذاكرة USB هذه سيعمل برنامج الإعداد الخاص بويندوز 10 ضمن سلسلة من الخطوات البسيطة التي ستتوّج بتنصيب ويندوز 10 على هذا الحاسوب. تبدأ هذه الخطوات بنافذة تخبرنا بنوع اللغة وإعدادات نسخة ويندوز التي سيتم تنصيبها على هذا الجهاز. حدّد الخيارات كما هو موضّح في الشكل السابق (أو حسبما ترغب) ثم انقر زر التالي. ستظهر نافذة أخرى انقر منها زر "التثبيت الآن". ستظهر بعد ذلك نافذة تنشيط ويندوز. أدخل فيها الرقم التسلسلي للنسخة التي لديك ثم انقر زر التالي. أمّا إذا لم تكن تمتلك رقمًا تسلسليًّا وأردت تجربة ويندوز 10 فيمكنك نقر "مفتاح المنتج غير موجود لدي" الموجود بجواز زر "التالي". ستخيّرنا النافذة التالية بين الإصدارين Windows 10 Home و Windows 10 Pro. اختر Windows 10 Pro ثم انقر زر "التالي". بعد ذلك ستظهر نافذة الترخيص. يمكنك تفقّد بنودها، ثم وافق عليها، وانقر زر "التالي". ستظهر بعد ذلك نافذة تحديد نوع التثبيت المرغوب به. كما في الشكل التالي: اختر الخيار الأول إذا أردت ترقية نظام الويندوز القديم الموجود أصلًا في الحاسوب أو يمكنك اختيار الخيار الثاني "مخصص" لتظهر بعد ذلك نافذة تحديد محرّك الأقراص المرغوب لتثبيت ويندوز ضمنه. يمكنك من خلال هذه النافذة تهيئة محركات الأقراص، وإنشاء أقراص جديدة، وحذفها. بعد اختيار محرّك الأقراص المناسب، انقر زر "التالي" لكي تبدأ عملية النسخ والإعداد. ستستغرق هذه العملية بعضًا من الوقت، بحسب سرعة جهاز الحاسوب لديك. بعد الانتهاء سيعرض برنامج الإعداد نافذة تستطيع من خلالها تحديد فيما إذا أردت استخدام الإعدادات السريعة أو أنّك تريد استخدام خيار التخصيص. سنختار هنا "استخدام الإعدادات السريعة". ستظهر بعد ذلك نافذة تسمح لك بكتابة اسم المستخدم الذي سيستخدم هذا الحاسوب، بالإضافة إلى تعيين كلمة مرور مناسبة، وتلميح لها، ثم انقر زر "التالي". عند هذه النقطة تكون عملية تنصيب ويندوز 10 قد انتهت، وسيظهر لك سطح المكتب للمرّة الأولى. الخطوة الأولى التي ينبغي القيام بها بعد تنصيب ويندوز هي التشبيك مع الإنترنت وتحديث ويندوز. وهذا ما سنتحدّث عنه بالإضافة إلى مواضيع أخرى في الدرس التالي. الخلاصة تعلّمنا من خلال هذا الدرس كيفيّة تنزيل نسخة ISO لويندوز 10 ونسخها إلى ذاكرة USB عن طريق برنامج اسمه Rufus، ثم نصّبنا ويندوز 10 من خلال ذاكرة USB بعد أن جعلنا الحاسوب يُقلع منها. إذا كنت تعمل في حقل الدعم الفني IT ربما ستجد هذه الطريقة مفيدة للغاية عند تنصيب ويندوز 10 على أكثر من حاسوب بنفس الوقت، حيث تستفيد من ميزة عدم إشغال الشبكة الخاصة بالشركة بتحميل نسخة الويندوز مباشرةً من الانترنت. أو عندما ترغب بتنصيب ويندوز 10 مباشرةً على حاسوب لا يحتوي على أيّ نظام تشغيل بشكل مسبق. سنتابع عملنا في هذه السلسلة في إجراء التحديث الأوليّ لويندوز 10 والتعرّف على المزايا الجديدة والمهمّة لنظام التشغيل الواعد من مايكروسوفت.
  2. سنتحدّث في هذا الدرس من سلسلة المقالات حول التعامل مع ويندوز 10 عن بعض التطبيقات المفيدة في ويندوز 10 والموجودة بصورة مسبقة في نظام التشغيل، وهي مجانية بالطبع. توجد العديد من التطبيقات من هذا النوع مثل تطبيقات الرياضة Sport والأخبار News والمال Money والخرائط Maps والملاحظات OneNote والطقس Weather. سنخصّ بالذكر التطبيقات الثلاثة الأخيرة. تطبيق الخرائط Maps هو من التطبيقات المفيدة في ويندوز 10 ويعطيك المزايا الأفضل بالنسبة لخرائط Bing وخرائط HERE. يتمتع هذا التطبيق بالعديد من المزايا التي سنستعرض بعضًا منها بعد قليل. انقر زر ابدأ واكتب مباشرةً كلمة "الخرائط" ليعمل ويندوز على البحث مباشرةً عن هذا التطبيق وإظهار نتيجة البحث المناسبة في الأعلى. انقر على أيقونة التطبيق لتظهر النافذة التالية: بعد أن تنقر زر "لنبدأ" ستظهر رسالة من التطبيق تسألك إذا كنت تريد السماح له بالوصول إلى موقعك الحالي. أجب بنعم، وانتظر قليلًا حتى تظهر النافذة الرئيسية له. ستظهر صورة عامّة للعالم، وتظهر فيها أيقونة دائرية صغيرة تُظهر موقعك التقريبي بهامش خطأ لا يتجاوز 7 كم. السبب في هامش الخطأ الكبير هذا، هو أنّني أشغّل هذا التطبيق من حاسوبي الشخصي الذي لا يمتلك جهاز GPS لتحديد المواقع. في حال تمّ تشغيل هذا التطبيق من جهاز يحتوي على جهاز GPS فسيكون موقعك دقيقًا على الخريطة. توجد العديد من المزايا المفيدة التي يمتلكها هذا التطبيق من بينها: يسمح للمستخدم بتثبيت المواقع المفضّلة ضمن شاشة البدء للوصول السريع لها فيما بعد. ويمكن استخدام هذا التطبيق على أجهزة الحاسوب المكتبيّة، كما يمكن استخدامه على الأجهزة الذكية المشغلة لنظام ويندوز، ويمكن استخدامه أيضًا مع نظارات مايكروسوفت الافتراضيّة Holographic. حفظ أي موقع جغرافي موجود على الخريطة، وإمكانية الوصول إليه من أي جهاز مرتبط بحساب مايكروسوفت الخاص بك. بالإضافة إلى حفظ نتائج البحث ومشاركتها باستخدام البريد الإلكتروني أو باستخدام برنامج OneNote الذي سنتحدّث عنه لاحقًا. يمكن مراقبة الحالة المروريّة للطرق بصورة حيّة مباشرة، إذا كانت توجد كاميرات مرورية تدعم النقل المباشر مثبتة على مثل هذه الطرق. يمكن تحميل الخرائط على الجهاز لاستخدامها لاحقًا دون الحاجة للاتصال بالإنترنت. توجد أدوات قياس جيدة لقياس المسافات على الخريطة يمكن الوصول إليها من خلال شريط الأدوات الموجود في الأعلى. يمكن من خلال هذه الأدوات قياس أي مسافة على الخريطة بالطول الحقيقي. تطبيق الملاحظات OneNote وهو أحد تطبيقات حزمة Office موجود بشكل مبسّط ومجاني في ويندوز 10 لكنّه مفيد. يستند هذا التطبيق على الصفحات في تدوين الملاحظات، حيث ينبغي إنشاء صفحات ذات تصنيف منطقي بما يلائم حاجات المستخدم. انقر زر ابدأ ثم اكتب بشكل مباشر الكلمة OneNote ليعمل ويندوز على إظهار أيقونة هذا التطبيق ليسمح لك بتشغيله. يمكن إنشاء صفحة جديدة من الجهة اليمنى لنافذة التطبيق، ثم نضع لها عنوانًا مناسبًا ونبدأ بتدوين الملاحظات التي تتنوّع بين ملاحظات نصيّة بسيطة أو محتوى غني يشتمل على إمكانيّة إدراج ملفات كاملة، أو حتى إدراج صورة ملتقطة مباشرةً من كاميرا الحاسوب (أو من كاميرا الجهاز الذكي). يمكن أيضًا إدراج ملاحظة على شكل رسم يتم رسمه مباشرةً (انظر لسان التبويب "رسم") باستخدام الفأرة. في الحقيقة ستكون ميزة الرسم مفيدة للغاية في حال كنت تستخدم حاسوبًا لوحيًا يمتلك قلمًا (مثل سلسلة حواسيب Surface). يمكن مزامنة الملاحظات بين جميع الأجهزة التي تستخدمها. وهذا يُعتبر أمرًا مهمًّا سواءً على المستوى الشخصي، أو حتى على مستوى العمل. حيث من الممكن مشاركة هذه الملاحظات مع أشخاص آخرين في حال رغبنا بذلك. تطبيق الطقس Weather رغم التنوّع الذي يمكن أن تجده في مثل هذه الصنف من التطبيقات، إلّا أنّ تطبيق الطقس الخاص بويندوز 10 له نكهة خاصّة! يرتبط هذا التطبيق في البداية بحساب مايكروسوفت الذي تستخدمه في تسجيل الدخول إلى ويندوز، ليضفي لمسة شخصيّة عليه. انقر زر ابدأ ثم اكتب مباشرةً كلمة "الطقس" ليعمل ويندوز على إظهار أيقونة هذا التطبيق. شغّل هذا التطبيق لتظهر نافذة الترحيب التالية: يمكنك أن تبحث عن موقعك الحالي من مربع "بحث" في الأسفل، أو أن تطلب من التطبيق معرفة موقعك الحالي بالنقر على الاختيار "اكتشف موقعي". إذا اخترت الأسلوب الأخير سيطلب منك ويندوز الموافقة على السماح لتطبيق الطقس بالوصول إلى موقعك. اقبل بذلك لكي يحدّد التطبيق موقعك الحالي. انقر زر بدء لكي يحمّل التطبيق بيانات الطقس الخاص بالموقع المحُدّد. انظر الشكل التالي: يمكنك عرض البيانات بشكل مختصر أو على بشكل تفصيلي كما يظهر من الشكل السابق. كما يمكنك استخدام شريط التمرير للوصول إلى أسفل الصفحة والاطلاع على بيانات متنوعة وغنيّة حول حالة الطقس والتنبؤ الجوي. الميزة الفريدة في هذا التطبيق هي ميزة "الخرائط" والتي يمكن الوصول إليها عن طريق النقر على الزر الموضّح في الشكل التالي وهو يقع ضمن الشريط العمودي الموجود على الطرف الأيمن من نافذة التطبيق. تعرض هذه الميزة تغيرات درجة الحرارة للمنطقة المطلوبة على شكل عرض فيديو تفاعلي على طول ساعات اليوم الواحد. انظر الشكل التالي: يمكن عرض نفس الخريطة التفاعلية السابقة ولكن بالنسبة لهطول الأمطار وصور الأقمار الصناعية والسُحُب أيضًا وذلك بالاختيار المناسب من القائمة الموجودة في الأعلى. يسمح هذا الفيديو التفاعلي بمراقبة تغيّرات الحالة الجويّة ابتداءً من الساعة الحالية وحتى اليوم التالي بنفس الساعة أي على مدار يوم كامل. يوفّر التطبيق أيضًا ميزة عرض بيانات قديمة للطقس لأغراض احصائيّة. الخلاصة تعرّفنا في هذا المقال على بعض التطبيقات المفيدة والمجّانيّة في ويندوز 10. وهي تطبيقات الطقس Weather والملاحظات OneNote والخرائط Maps. توجد العديد من التطبيقات الأخرى المجانيّة أيضًا في ويندوز 10 والتي لا يسعفنا المقال الحالي للحديث عنها. يمكنك أن تتعرّف عليها بنفسك لكي تستخدمها بالشكل الذي يناسب احتياجاتك.
  3. سنبدأ في هذا الدرس من سلسلة إعداد واستخدام ماجنتو بالتعرف على كيفيّة إضافة المنتجات البسيطة إلى ماجنتو. حيث سنعمل على اتباع الخطوات اللازمة لإضافة منتج بسيط. سيكون هذا الدرس كحجر بناء لإضافة العديد من أنواع المنتجات الأخرى -كما سنرى في درس لاحق- وذلك لأنّ المنتج البسيط كما وسبق أن أوضحنا سابقًا، يدخل في تكوين العديد من أنواع المنتجات الأخرى التي يدعمها ماجنتو. من المفيد أن تكون قد اطلعت على الدرس الخاص بأنواع المنتجات في ماجنتو. بدايةً وقبل إضافة أي منتج، يتوجّب علينا إضافة فئة (صنف) Category واحدة على الأقل يتبع لها المنتج. سنتحدّث في البداية عن كيفيّة إضافة مثل هذه الفئات، ثم ننتقل إلى عمليّة إضافة المنتجات. إنشاء فئة Category جديدة انتقل إلى القائمة الجانبيّة الخاصّة بمدير النظام واختر منها PRODUCTS، ومن القائمة الصغيرة التي ستظهر اختر الفئات Categories. بعد أن تظهر الصفحة المطلوبة انقر الزر Add Subcategory الموجود في أعلى ويسار الصفحة وذلك لإضافة فئة فرعية إلى الفئة الافتراضية Default Categroy. لتظهر بعد ذلك الصفحة المسؤولة عن إضافة فئة جديدة. كما في الشكل التالي: اختر الاسم T-Shirts للحقل Category Name. لاحظ معي وجود العديد من الخيارات المتعلّقة بالفئة المراد إضافتها. والتي تتعلّق بالمحتوى وبكيفيّة الظهور وبالتصميم، وحتى بالمنتجات التابعة لها. سنكتفي بكتابة اسم هذه الفئة حاليًا. انقر الآن زر Save البرتقالي اللون في الجهة العليا اليمنى من الصفحة. إنشاء منتج بسيط Simple Product بعد إضافة الفئة السابقة يمكننا الآن إضافة منتج بسيط، وذلك بالانتقال إلى القائمة الجانبيّة الخاصّة بمدير النظام، واختيار PRODUCTS، ومن القائمة الصغيرة التي ستظهر سنختر Catalog. بعد ظهور الصفحة المطلوبة. انقر السهم الصغير الموجود ضمن الزر البرتقالي اللون المسمى Add Products (في الجهة اليمنى العليا) لتظهر قائمة صغيرة، اختر منها Simple Product. أي أنّنا نريد إضافة منتج بسيط جديد. ستظهر الصفحة الخاصة بإضافة منتج بسيط. تحتوي هذه الصفحة على العديد من الخيارات المصنّفة والتي تضبط سلوك هذا المنتج. سنعمل على ضبط الحقول العامة التالية لهذا المنتج الجديد: الحقل Product Name سيحمل القيمة Hsoub T-Shirt. الحقل Price سيحمل القيمة 20. الحقل Quantity سيحمل القيمة 50. أمّا بالنسبة للحقل Categories فسنختار من القائمة المنسدلة الفئة التي أنشأناها في الفقرة السابقة وهي T-Shirts. بعد ذلك يمكنك استخدام شريط التمرير للانتقال أسفل الصفحة إلى التصنيف Content الذي يُعبّر عن محتوى الصفحة الخاصّة بهذا المنتج، انقر على المؤشّر الصغير الموجود على يمين هذا التصنيف لنشر محتواه كما يظهر في الشكل التالي: اكتب وصفًا عامًا للمنتج ضمن الحقل Description، ووصفًا مختصرًا له ضمن الحقل Short Description الذي يظهر بعد الحقل السابق (حقل Description): ثم انتقل بعد ذلك باستخدام شريط التمرير إلى الأسفل إلى التصنيف Images And Videos لإضافة صورة أو مقطع فيديو إن أحببت. بعد ذلك انقر زر الحفظ البرتقالي Save الذي يظهر أعلى يمين الصفحة ليتمّ إضافة هذا المنتج البسيط. من الممكن أن تكون قد لاحظت أيضًا الوجود العديد من الخيارات الأخرى التي يمكن ضبطها لهذا المنتج. ولكنّنا وبغرض تبسيط الأمور اعتمدنا على الخيارات الأدنى لإنشائه. زيارة صفحة المتجر لاستعراض المنتج الجديد من الجميل أن نتفقّد الآن صفحة الويب الخاصة بالمتجر لتفقّد الإضافات الجديدة التي عملنا عليها في الفقرات السابقة. افتح لسان تبويب جديد من متصفّح الإنترنت لديك. ثم اكتب العنوان التالي: http://127.0.1.1/magento سيؤدّي ذلك إلى الانتقال إلى الصفحة الرئيسيّة للموقع، والتي من المفترض أن تظهر للعميل عند زيارته للموقع بشكل عام. انظر الشكل التالي: من الملفت للنظر بدايةً أنّ الصفحة الرئيسية للموقع فارغة من المحتوى. وهذا أمر طبيعي تمامًا لأنّنا لم نجهّز المحتوى بعد. سنتناول هذا الموضوع في درس لاحق. نلاحظ الآن ظهور الفئة الجديدة T-Shirts على شريط الفئات في الأعلى. إذا حاولت نقر هذه الفئة، سينتقل بك المتصفّح إلى صفحة المنتجات الخاصة بهذه الفئة. انظر الشكل التالي: لا يوجد حاليًا سوى منتج واحد فقط، وهو Hsoub T-Shirt الذي أضفناه قبل قليل. أنصحك بإضافة المزيد من المنتجات لترى تأثير ذلك. انقر على هذا المنتج الوحيد، لتظهر الصفحة التفصيليّة للمنتج، والتي ستحتوي على جميع المعلومات التي كتبناها مسبقًا حوله. انظر إلى الشكل التالي: يمكننا أيضًا البحث عن المنتج باستخدام ميزة البحث الموجودة في ماجنتو. انتقل إلى الصفحة الرئيسية للمتجر مرّة أخرى. ثم من الزاوية اليمنى العليا ستلاحظ وجود مربّع خاص للبحث ضمن المتجر. اكتب كلمة البحث التي تريدها ولتكن T-Shirts مثلًا، ثم اضغط المفتاح Enter ليبدأ ماجنتو بالبحث وإيجاد المنتجات التي تتعلّق بالفئة T-Shirts. سيكون هناك كما هو واضح منتج واحد فقط حاليًا ضمن نتائج البحث. خلاصة تناولنا في هذا الدرس كيفيّة إنشاء فئة (صنف) Category جديدة للمنتجات في ماجنتو. وكيفيّة إضافة منتج بسيط Simple Product لهذه الفئة. يُعتبر المنتج البسيط كما أشرنا من قبل المنتج الأساسي الذي تُبنى عليه العديد من أنواع المنتجات الأخرى. سنتابع العمل على إضافة أنواع منتجات أخرى تعتمد في تكوينها على المنتج البسيط، وذلك في الدرس التالي.
  4. السبب هو الحاجة إلى السرعة الكبيرة. لا تنسى أنّ موقع يوتيوب هو موقع يتعامل في الأساس مع الفيديو. وهي بيانات ذات حجم كبير وثقل لا يستهان به في المعالجة. على العموم "حسب معلوماتي"، فإنّ شركة غوغل المالكة ليوتيوب لا تتعامل أصلًا مع PHP.
  5. الحقيقة لم أستطع تحديد المشكلة في هذا الكود. أحتاج إلى الحصول على نسخة من المشروع - على الأقل من صفحة التحميل مع الشيفرة الخاصة بها.
  6. هذا دليل ان الكود المسؤول عن رفع الملف غير صحيح. ادرج الكود المسؤول عن الرفع
  7. يعني عندما رفعت الملف simple.txt إلى السيرفر وجربت فتح الملف على السيرفر هل نجحت بفتحه وظهرت لك الكلمة Hello ؟
  8. أخي الكريم. لقد غيرت امتداد الملف الذي أرفقته إلي وجعلته html. ظهر الملف ضمن المتصفح كما في المرفق والذي يمثل كما أظن صفحة التحميل الرئيسية لتطبيقك. على ما يبدو أنّك لا تحفظ الملف ضمن قاعدة البيانات. إنما الذي تحفظه هو صفحة التحميل نفسها وهذا خطأ بالطبع.
  9. اهلا اخي احتاج الى وصف دقيق لما طلبته منك في البنود الثلاث السابقة فحسب كي استطيع تشخيص المشكلة بدقة. على العموم يبدو ان الشيفرة التي تستخدمها غير صحيحة (كنظرة اولية)
  10. 1- أنشئ ملف نصي بسيط اسمه simple.txt واكتب فيه الكلمة التالية: Hello ثم احفظه. 2- ارفع الملف ثمّ تأكّد أنّه موجود على السيرفر ضمن المسار: ~//Files//simple.txt 3- نزّل الملف simple.txt وحاول فتحه. إذا نجحت بفتحه فما هي محتوياته؟ أرجو تنفيذ الخطوات الثلاث السابقة، وإعطائي وصف دقيق عن ملاحظاتك حول كل خطوة.
  11. أحتاج إلى معرفة بنية الجدول TBL_Files (الحقول مع أنواعها). يمكنك أخذ صورة للشاشة.
  12. إذا كنت تستطيع استخدام المنقّح Debugging فأضف نقطة توقّف Break Point ضمن الشيفرة المسؤولة عن جلب الملف من قاعدة البيانات عندما يطلب المستخدم تنزيله. انظر إلى حجم الملف الذي تمّ جلبه من قاعدة البيانات هل هو 86.7 كيلو بايت؟
  13. أجر اختبارًا بسيطًا. انظر بدقة إلى حجم الملف قبل رفعه. ثم نزله وانظر إلى حجمه مرة أخرى هل هناك أي فرق؟
  14. السلام عليكم أعتذر عن التأخر في الرد. يبدو أن نظام الاشعار في الموقع لا يعمل. لا أدري إن كانت المشكلة مازالت قائمة. إذا كان بالإمكان أن تحددي نظام التشغيل لديك.
  15. تحدثنا في الدرس السابق عن المخطّط المطلق Absolute Layout وعن فائدته في التحكّم بمواضع وأحجام العناصر المرئيّة باستخدام الواحدات المستقلة عن الجهاز independent-device units. سنتابع عملنا في هذا الدرس ضمن سلسلة تعلّم برمجة تطبيقات أندرويد باستخدام Xamarin.Forms ببناء تطبيق عمليّ جميل يُعتبر تحسينًا لتطبيق تحريك المربّعات الثلاثة المتداخلة الذي أوردناه في نهاية الدرس السابق. يوضّح لنا هذا التطبيق المُحسّن كيفيّة التحكّم بهذه المربّعات باستخدام أزرار تمثّل الاتجاهات الأربعة الأساسيّة (أعلى – أسفل - يمين – يسار). وصف التطبيق واجهة هذا التطبيق بسيطة. فبالإضافة إلى المربّعات الثلاثة. سنضع أربعة أزرار عاديّة تمثّل الاتجاهات الأربعة الأساسيّة. بحيث تتوضّع هذه المربّعات أسفل ووسط الشاشة. عند بدء تشغيل التطبيق سنحصل على شكل شبيه بما يلي: لاحظ كيف تتوسّط الأزرار الأربعة الشاشة أفقيًّا، سنوضّح سبب ذلك بعد قليل. إذا حاول المستخدم في الوضع الحالي نقر أي زر من الأزرار الأربعة السابقة سيعرض له البرنامج رسالة يطلب منه فيها اختيار أحد المربّعات أولًا لتحريكه. عندما ينقر المستخدم على أحد المربّعات السابقة، ستتلوّن الأزرار الأربعة بنفس لون المربّع الذي نقره المستخدم. وعندها فقط يمكن استخدام الأزرار لتحريك المربّع المُختار في أيّ اتجاه يرغبه. في الشكل التالي قمت باختيار المربّع الأحمر، ومن ثمّ تحريكه إلى الأعلى ثم إلى اليمين: يمكنك تكرار نفس الخطوات السابقة لتحريك أيّ مربّع آخر. هذا هو مبدأ هذا البرنامج، وهو بسيط كما ترى، ولكن سنتعلّم من خلاله بعض التقنيّات المفيدة في ضبط التموضع ضمن المخطّط المطلق، بالإضافة إلى تعلّم كيفيّة إكساب عناصر BoxView قابلية الاستجابة إلى أحداث اللمس كما سنرى بعد قليل. تطبيق تحريك المربّعات باستخدام الأزرار أنشئ مشروعًا جديدًا من النوع Blank App (Xamarin.Forms Portable) وسمّه MoveSquaresByButtons، ثم أبق فقط على المشروعين MoveSquaresByButtons (Portable) و MoveSquaresByButtons.Droid كما وسبق أن فعلنا في هذا الدرس. بعد ذلك سنضيف صفحة محتوى تعتمد على رُماز XAML كما وسبق أن فعلنا في هذا الدرس سنسمّيها MoveSquaresByButtonsPage. احرص على أن تكون محتويات هذه الصفحة على الشكل التالي: 1 <?xml version="1.0" encoding="utf-8" ?> 2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 4 x:Class="MoveSquaresByButtons.MoveSquaresByButtonsPage" 5 SizeChanged="PageResize"> 6 7 <AbsoluteLayout> 8 <BoxView x:Name="boxAccent" 9 Color="Accent" 10 AbsoluteLayout.LayoutBounds="25, 100, 100, 100" 11 Opacity="0.5" /> 12 13 <BoxView x:Name="boxRed" 14 Color="Red" 15 AbsoluteLayout.LayoutBounds="75, 150, 100, 100" 16 Opacity="0.5"/> 17 18 <BoxView x:Name="boxGreen" 19 Color="Green" 20 AbsoluteLayout.LayoutBounds="125, 200, 100, 100" 21 Opacity="0.5"/> 22 23 <Button x:Name="btnMoveUp" 24 StyleId="MoveBoxUp" 25 Clicked="MoveBox_Clicked" 26 FontSize="Large" 27 BorderWidth="0" 28 Text="↑"/> 29 30 <Button x:Name="btnMoveDown" 31 StyleId="MoveBoxDown" 32 Clicked="MoveBox_Clicked" 33 FontSize="Large" 34 BorderWidth="0" 35 Text="↓"/> 36 37 <Button x:Name="btnMoveRight" 38 StyleId="MoveBoxRight" 39 Clicked="MoveBox_Clicked" 40 FontSize="Large" 41 Text="→"/> 42 43 <Button x:Name="btnMoveLeft" 44 StyleId="MoveBoxLeft" 45 Clicked="MoveBox_Clicked" 46 FontSize="Large" 47 Text="←"/> 48 </AbsoluteLayout> 49 50 </ContentPage> لاحظ معي أنّ عناصر BoxView الموجودة في الأسطر من 8 حتى 21 هي نفسها الموجودة في تطبيق المربّعات المتداخلة من الدرس السابق. الجديد هنا هو تعيين معالج للحدث SizeChanged للصفحة (السطر 5) الذي يُستدعى كلّما اقتضت الحاجة إلى تغيير حجم الصفحة، وهو يحدث عادةً عند البدء بتشغيل التطبيق، وأيضًا عندما يُغيّر المستخدم اتجاه الجهاز من عمودي إلى أفقي أو بالعكس. الجديد هنا أيضًا هو الأزرار الأربعة الموجودة في الأسطر من 23 حتى 47. من الواضح أنّ جميع العناصر المرئيّة السابقة موجودة ضمن مخطّط مطلق AbsoluteLayout يضمن لنا التحكّم بمواقعها وبأحجامها كما أشرنا. تأمّل معي هذا الرماز الذي يمثّل زر الحركة نحو الأعلى: <Button x:Name="btnMoveUp" StyleId="MoveBoxUp" Clicked="MoveBox_Clicked" FontSize="Large" BorderWidth="0" Text="&#8593;"/> لقد وضعت القيمة "MoveBoxUp" للخاصيّة StyleId حيث سنستفيد منها ضمن معالج الحدث MoveBox_Clicked الذي أسندته للحدث Clicked كما هو واضح. سنرى بعد قليل الشيفرة البرمجيّة الخاصّة بهذا المعالج. الأمر الملفت هنا هو القيمة "&H8593;" التي ضبطُّها لخاصيّة النص. سيؤدي ذلك إلى وضع رمز السهم المتجه إلى أعلى ليظهر على هذا الزر. بنفس هذا الأسلوب تمّ تجهيز الأزرار الثلاثة الباقية التي سأسند إلى كلّ منها قيمة مختلفة للخاصيّة StyleId لتعبّر عن وظيفتها، ولكن مع إسناد نفس معالج الحدث MoveBox_Clicked لجميعها. لننتقل الآن إلى ملف الشيفرة البرمجية الموافق لصفحة المحتوى السابقة. احرص على أن تكون محتوياته على الشكل التالي: 1 using System; 2 using Xamarin.Forms; 3 4 namespace MoveSquaresByButtons 5 { 6 public partial class MoveSquaresByButtonsPage : ContentPage 7 { 8 private BoxView selectedBoxView; 9 private const double BUTTON_MARGIN = 5; 10 private const double PAGE_BUTTOM_MARGIN = 10; 11 private const double MOVE_AMOUNT = 15; 12 13 public MoveSquaresByButtonsPage() 14 { 15 InitializeComponent(); 16 17 TapGestureRecognizer tapGesture = new TapGestureRecognizer(); 18 19 tapGesture.Tapped += TapGesture_Tapped; 20 21 boxAccent.GestureRecognizers.Add(tapGesture); 22 boxRed.GestureRecognizers.Add(tapGesture); 23 boxGreen.GestureRecognizers.Add(tapGesture); 24 } 25 26 private void TapGesture_Tapped(object sender, EventArgs e) 27 { 28 selectedBoxView = (BoxView)sender; 29 30 btnMoveUp.BackgroundColor = selectedBoxView.Color; 31 btnMoveDown.BackgroundColor = selectedBoxView.Color; 32 btnMoveLeft.BackgroundColor = selectedBoxView.Color; 33 btnMoveRight.BackgroundColor = selectedBoxView.Color; 34 } 35 36 37 private void MoveBox_Clicked(object sender, EventArgs e) 38 { 39 Button moveButton = (Button)sender; 40 Rectangle rect; 41 42 if (selectedBoxView == null) 43 { 44 DisplayAlert("اختيار مربع", "اختر مربّعًا من فضلك", "موافق"); 45 return; 46 } 47 48 rect = AbsoluteLayout.GetLayoutBounds(selectedBoxView); 49 50 if (moveButton.StyleId == "MoveBoxUp") 51 { 52 rect = new Rectangle(rect.X, rect.Y - MOVE_AMOUNT, rect.Width, rect.Height); 53 } 54 else if (moveButton.StyleId == "MoveBoxDown") 55 { 56 rect = new Rectangle(rect.X, rect.Y + MOVE_AMOUNT, rect.Width, rect.Height); 57 } 58 else if (moveButton.StyleId == "MoveBoxRight") 59 { 60 rect = new Rectangle(rect.X + MOVE_AMOUNT, rect.Y, rect.Width, rect.Height); 61 } 62 else if (moveButton.StyleId == "MoveBoxLeft") 63 { 64 rect = new Rectangle(rect.X - MOVE_AMOUNT, rect.Y, rect.Width, rect.Height); 65 } 66 67 AbsoluteLayout.SetLayoutBounds(selectedBoxView, rect); 68 } 69 70 private void PageResize(object sender, EventArgs e) 71 { 72 ContentPage page = (ContentPage)sender; 73 74 double buttonWidth = btnMoveUp.Width; 75 double buttonHeight = btnMoveUp.Height; 76 double buttonsAreaWidth = buttonWidth * 3 + BUTTON_MARGIN * 2; 77 double buttonsAreaLeftDisplacement = (page.Width - buttonsAreaWidth) / 2; 78 79 AbsoluteLayout.SetLayoutBounds(btnMoveDown, 80 new Rectangle(buttonsAreaLeftDisplacement + buttonWidth + BUTTON_MARGIN, 81 page.Height - buttonHeight - PAGE_BUTTOM_MARGIN, 82 buttonWidth, 83 buttonHeight)); 84 85 AbsoluteLayout.SetLayoutBounds(btnMoveUp, 86 new Rectangle(buttonsAreaLeftDisplacement + buttonWidth + BUTTON_MARGIN, 87 page.Height - buttonHeight * 2 - BUTTON_MARGIN - PAGE_BUTTOM_MARGIN, 88 buttonWidth, 89 buttonHeight)); 90 91 92 AbsoluteLayout.SetLayoutBounds(btnMoveLeft, 93 new Rectangle(buttonsAreaLeftDisplacement, 94 page.Height - 3 * buttonHeight / 2 - PAGE_BUTTOM_MARGIN, 95 buttonWidth, 96 buttonHeight)); 97 98 AbsoluteLayout.SetLayoutBounds(btnMoveRight, 99 new Rectangle(buttonsAreaLeftDisplacement + buttonWidth * 2 + BUTTON_MARGIN * 2, 100 page.Height - 3 * buttonHeight / 2 - PAGE_BUTTOM_MARGIN, 101 buttonWidth, 102 buttonHeight)); 103 } 104 } 105 } يحتوي الصنف MoveSquaresByButtonsPage بشكل أساسيّ على بانية وعدّة توابع هي في الواقع معالجات للأحداث التي يحتاج إليها التطبيق. سنتحدّث عنها بشيء من التفصيل. البانية إذا نظرت إلى البانية (الأسطر من 13 حتى 24) فستجد أنّنا نعرّف ضمنها كائنًا من النوع TapGestureRecognizer (السطر 17) سنُسند هذا الكائن إلى المتغيّر tapGesture كما هو واضح. يفيد هذا الكائن في إكساب عنصر BoxView قابلية النقر لأنّه –وبشكل مغاير لعنصر الزر Button- لا يمتلكها أصلًا. نعمل في السطر 19 على تعيين معالج لحدث النقر (اللمس) Tapped للكائن السابق واسمه TapGesture_Tapped (سنتحدّث عنه بعد لحظة). العملية الأخيرة التي نجريها في البانية هي إضافة الكائن tapGesture إلى كل من المربّعات الثلاثة عن طريق التابع Add للمجموعة GestureRecognizers لكل مربع من هذه المربعات (الأسطر من 21 حتى 23). معالج حدث النقر على المربّعات TapGesture_Tapped يمكنك رؤية هذا المعالج في الأسطر من 26 حتى 34. الذي يحدث ضمن هذا المعالج هو أنّنا نحصل على مرجع المربّع الذي نقره المستخدم (السطر 28) ونُسنده إلى الحقل selectedBoxView وهو حقل خاص من النوع BoxView مصرّح عنه في السطر 8، ثم نلوّن أزرار التحريك الأربعة بنفس لون المربّع الذي نقره (لمسه) المستخدم. معالج حدث النقر على الأزرار MoveBox_Clicked بالنسبة لمعالج الحدث MoveBox_Clicked وهو موجود في الأسطر من 37 حتى 68 فهو يُستدعى عندما ينقر المستخدم أيًا من أزرار التحريك الأربعة. ووظيفته هو تحريك المربّع الذي اختاره المستخدم مسبقًا في الاتجاه المطلوب. نحصل في السطر 39 على مرجع الزر الذي تمّ نقره، ثمّ نختبر فيما إذا كان المستخدم قد قام فعلًا باختيار مربّع من قبل (الأسطر من 42 حتى 46) حيث يُعطي التطبيق تنبيهًا للمستخدم في حال لم يكن قد اختار مربّعًا من قبل. انظر الآن إلى السطر 48: rect = AbsoluteLayout.GetLayoutBounds(selectedBoxView); يُرجع التابع GetLayoutBounds من الصنف AbsoluteLayout بنية من النوع Rectangle لأيّ عنصر مرئي نمرّره له موجود ضمن المخطّط المطلق. نحتاج هنا إلى معرفة المستطيل المُحدّد للمربّع الذي اختاره المستخدم من قبل. يُعطينا المستطيل المحدّد معلومات حول إحداثيّي الزاوية اليسرى العليا للمربّع (الإحداثي X والإحداثي Y) بالإضافة إلى عرض Width وارتفاع Height المربّع. تقارن بعد ذلك عبارات if الموجودة في الأسطر من 50 حتى 65 الخاصيّة StyleId للزر الذي نقره المستخدم مع عدّة نصوص معدّة سلفًا، لمعرفة الاتجاه المطلوب التحريك وفقه. لكي يتمكّن البرنامج من تعديل الإحداثي المطلوب على المستطيل المحدّد للمربّع وذلك بالانتقال المسافة المعيّنة بالثابت MOVE_AMOUNT الذي عرّفناه في السطر 11. بعد ذلك يتم تعيين المستطيل المحدّد الجديد (بعد التعديل) إلى المربّع نفسه (السطر 67) مما يؤدي إلى إعطاء انطباع بالحركة. معالج حدث تغيير حجم الصفحة PageResize بالنسبة للمعالج PageResize (الأسطر من 70 حتى 103) فهو يُستدعى عندما يطرأ تعديل على حجم الصفحة. وتنحصر وظيفة هذا المعالج في الحقيقة بوضع أزرار الحركة الأربعة بالشكل الذي أوضحناه أوّل الدرس. حيث يعتمد على ثابتين: الثابت BUTTON_MARGIN (مصرّح عنه في السطر 9) ويمثّل التباعد بين أيّ زرّين. الثابت PAGE_BUTTOM_MARGIN (مصرّح عنه في السطر 10) ويمثّل الهامش السفلي لزر الحركة نحو الأسفل وذلك عن أسفل الشاشة. الأمر الملفت ضمن هذا المعالج هو كيفية حساب مسافة الإزاحة الأفقيّة لتوسيط مجموعة الأزرار أفقيًّا، حيث يتم ذلك بأسلوب حسابي بسيط. إذ أنّ الشيفرة تحسب العرض الإجمالي لثلاثة أزرار مضافًا إليها قيمتي هامشين (بين كل زرين هامش) وتضعه ضمن المتغيّر buttonsAreaWidth: double buttonsAreaWidth = buttonWidth * 3 + BUTTON_MARGIN * 2; ثمّ تقوم بطرح القيمة السابقة من عرض الصفحة page.Width وتقسّمه على 2. فنحصل على مقدار الإزاحة الأفقيّة الواجب تطبيقها من الجهة اليسرى وتضعها ضمن المتغيّر buttonsAreaLeftDisplacement: double buttonsAreaLeftDisplacement = (page.Width - buttonsAreaWidth) / 2; ما تبقى من عبارات برمجيّة هي بسيطة في الواقع ولا تعدو عن كونها عبارات تنظيميّة تهدف إلى وضع الأزرار على نحو متناسق. انتقل أخيرًا إلى الملف App.cs واحرص على أن تكون بانيته على الشكل التالي: public App() { // The root page of your application MainPage = new MoveSquaresByButtonsPage(); } أصبح التطبيق جاهزًا للتنفيذ. يمكنك تنفيذه بضغط المفتاح F5 كما تعلّمنا. الخلاصة تحدثنا في هذا الدرس عن تطبيق عمليّ يعتمد على المخطّط المطلق Absolute Layout. حيث تعلّمنا كيفيّة التحكم الدقيق بمواضع العناصر لإكساب واجهة المستخدم شكلًا دقيقًا مُعد مسبقًا. كما تعلّمنا كيفيّة إكساب أيّ عنصر من النوع BoxView إمكانية الاستجابة لحدث النقر عن طريق كائن من الصنف TapGestureRecognizer. وتعلّمنا أيضًا تقنيّات بسيطة لتحريك العناصر المرئية على الشاشة. سننهي بهذا المقال حديثنا عن المخطّطات التي تدعمها Xamarin. في الحقيقة يُعتبر الفهم الجيّد للمخطّطات مفتاحًا أساسيًّا لبناء واجهة المستخدم.
  16. المخطّط المطلق Absolute Layout هو من المخطّطات المعتمدة في Xamarin، وتقوم فكرته على السماح للعناصر المرئيّة الموجودة ضمنه بأن يكون تموضعها بشكل مطلق، أي من الممكن ضبط مكان التموضع بالإضافة إلى عرض وارتفاع كل عنصر مرئي بشكل دقيق باستخدام الواحدات المستقلة عن الجهاز independent-device units. ولعلّ هذا المفهوم ليس جديدًا، بل هو من المفاهيم القديمة في عالم البرمجة، فقد كان المبرمجون قديمًا (وما زالوا في بعض الأحيان حتى اليوم) يعتمدون على بناء واجهات التطبيقات بتعريف موضع وأبعاد (العرض والارتفاع) كل عنصر بشكل دقيق ضمن الواجهة. سنطّلع في هذا الدرس ضمن سلسلة تعلّم برمجة تطبيقات أندرويد باستخدام Xamarin.Forms على كيفيّة التعامل مع هذا المخطّط باستخدام رماز XAML من خلال تطبيقين بسيطين. تطبيق المربّعات المتداخلة تعتمد فكرة هذا التطبيق على وجود 3 مربّعات متداخلة فيما بينها بحيث يمتلك كلّ منها شفافيّة بمقدار 50%. ستكون هذه المربّعات ضمن مخطّط مطلق Absolute Layout، وكلّ منها عبارة عن كائن ViewBox. سنعيّن مواقع وأبعاد هذه المربّعات باستخدام الواحدات المستقلة عن الجهاز independent-device units. أنشئ مشروعًا جديدًا من النوع Blank App (Xamarin.Forms Portable) وسمّه SimpleAbsoluteLayout، ثم أبق فقط على المشروعين SimpleAbsoluteLayout (Portable) و SimpleAbsoluteLayout.Droid كما وسبق أن فعلنا في هذا الدرس. بعد ذلك سنضيف صفحة محتوى تعتمد على رماز XAML كما وسبق أن فعلنا في هذا الدرس سنسمّيها SimpleAbsoluteLayoutPage. احرص على أن تكون محتويات هذه الصفحة على الشكل التالي: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleAbsoluteLayout.SimpleAbsoluteLayoutPage"> <AbsoluteLayout x:Name="absLayout"> <BoxView x:Name="boxAccent" Color="Accent" AbsoluteLayout.LayoutBounds="25, 100, 110, 110" Opacity="0.5"/> <BoxView x:Name="boxRed" Color="Red" AbsoluteLayout.LayoutBounds="50, 125, 110, 110" Opacity="0.5"/> <BoxView x:Name="boxGreen" Color="Green" AbsoluteLayout.LayoutBounds="75, 150, 110, 110" Opacity="0.5"/> </AbsoluteLayout> </ContentPage> محتويات هذه الصفحة بسيطة وواضحة. حيث نعمل على إنشاء مخطّط مطلق باستخدام الوسم . لاحظ كيف وضعنا ضمن هذا العنصر ثلاثة عناصر من النوع BoxView. وقد عيّنّا لكل عنصر منها اسمًا لأنّنا سنحتاجه في القسم الثاني من هذا الدرس. الملفت للنظر أنّ هذه العناصر قد تمّ وضعها مباشرةً ضمن العنصر AbsoluteLayout دون الحاجة إلى وجود الوسم وهذا جائز تمامًا. لاحظ بالنسبة إلى عنصر BoxView الأوّل: <BoxView x:Name="boxAccent" Color="Accent" AbsoluteLayout.LayoutBounds="25, 100, 110, 110" Opacity="0.5"/> الخاصيّة التي تتحكّم بموضعه هي AbsoluteLayout.LayoutBounds حيث أسندنا إليها النص: "25, 100, 110, 110" الذي يحتوي على أربعة أرقام تفصل بينها فواصل، وهي من اليسار إلى اليمين: بعد الزاوية اليسرى العليا من العنصر عن الحافة اليسرى للمخطّط المطلق ورمزه X (القيمة 25). بعد الزاوية اليسرى العليا من العنصر عن الحافة العليا للمخطّط المطلق ورمزه Y (القيمة 100). عرض العنصر ورمزه Width (القيمة 110). ارتفاع العنصر ورمزه Height (القيمة 110). انظر الشكل التخطيطي التالي لمزيد من التوضيح: في الحقيقة يمكنك اعتبار الشكل السابق كجملة إحداثية ديكارتيّة، ولكنّ محور التراتيب y-axis موجّه نحو الأسفل كما هو واضح بدلًا من الاتجاه المألوف نحو الأعلى. ينطبق نفس الأمر تمامًا على عنصريّ BoxView الباقيين: <BoxView x:Name="boxRed" Color="Red" AbsoluteLayout.LayoutBounds="50, 125, 110, 110" Opacity="0.5"/> <BoxView x:Name="boxGreen" Color="Green" AbsoluteLayout.LayoutBounds="75, 150, 110, 110" Opacity="0.5"/> وبما أنّ لكل من هذه العناصر الثلاثة نفس القيمة للعرض وللارتفاع، إذًا فهي عبارة عن مربّعات، وهي طبوقة فيما بينها. إذا نظرت إلى الأرقام الخاصّة بالموضع وبالحجم التي اخترتها "للمربّعات" الثلاث، فستلاحظ أنّني اخترتها بعناية كي تكون متداخلة فيما بينها. وقد جعلت الشفافيّة (الخاصية Opacity) لكلّ منها 50% (القيمة 0.5) لكي تعطي ذلك التأثير اللوني الجميل عندما تتداخل مع بعضها. انتقل الآن إلى الملف App.cs واحرص على ان تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new SimpleAbsoluteLayoutPage(); } نفّذ التطبيق باستخدام F5، لتحصل على شكل شبيه بما يلي: لنحرّك المربّعات! لنعمل على إضفاء القليل من الإثارة على التطبيق السابق. سنعمل على تحريك المربّعات السابقة بحركة رأسيّة تلقائيّة. أي أنّ المربّعات السابقة ستتحرّك نحو الأعلى حتى تصل إلى الحافة العليا للشاشة، ثم تعكس اتجاه الحركة نحو الأسفل حتى تصل إلى الحافة السفلى من الشاشة. ثم تعود من جديد لتعكس جهة الحركة لتصبح نحو الأعلى، وهكذا دواليك. في الحقيقة لن يطرأ أيّ تغيير على رماز XAML، فكل ما سنفعله هو إضافة الشيفرة البرمجيّة المناسبة لملف الشيفرة البرمجيّة الموافق لملف الرماز السابق. انتقل الآن إلى الملف SimpleAbsoluteLayoutPage.xaml.cs واحرص على أن تكون محتوياته على الشكل التالي: 1 using System; 2 using Xamarin.Forms; 3 4 namespace SimpleAbsoluteLayout 5 { 6 public partial class SimpleAbsoluteLayoutPage : ContentPage 7 { 8 private bool isUpDirection; 9 public SimpleAbsoluteLayoutPage() 10 { 11 InitializeComponent(); 12 13 isUpDirection = false; 14 15 Device.StartTimer(TimeSpan.FromMilliseconds(50), UpdatePositions); 16 } 17 18 private bool UpdatePositions() 19 { 20 Rectangle rect; 21 22 rect = AbsoluteLayout.GetLayoutBounds(boxAccent); 23 if (rect.Y - 10 <= 0) 24 { 25 isUpDirection = false; 26 } 27 28 rect = AbsoluteLayout.GetLayoutBounds(boxGreen); 29 if (rect.Y + rect.Height + 10 > this.Height) 30 { 31 isUpDirection = true; 32 } 33 34 BoxView[] boxViews = { boxAccent, boxRed, boxGreen }; 35 36 for (int i = 0; i < boxViews.Length; i++) 37 { 38 rect = AbsoluteLayout.GetLayoutBounds(boxViews[i]); 39 40 if (isUpDirection) 41 { 42 rect = new Rectangle(rect.X, rect.Y - 10, rect.Width, rect.Height); 43 } 44 else 45 { 46 rect = new Rectangle(rect.X, rect.Y + 10, rect.Width, rect.Height); 47 } 48 49 AbsoluteLayout.SetLayoutBounds(boxViews[i], rect); 50 } 51 52 return true; 53 } 54 } 55 } بالإضافة إلى بانية الصنف SimpleAbsoluteLayoutPage أنشأت تابعًا جديدًا أسميته UpdatePositions يمكنك أن تجده في الأسطر من 18 حتى 53. يُعتبر هذا التابع مسؤولًا عن تحريك المربّعات الثلاثة بالحركة الرأسيّة التي تحدثنا عنها قبل قليل. يتمّ استدعاء هذا التابع بشكل تلقائيّ كل 50 ميللي ثانيّة. التقنيّة التي استخدمناها في هذا الاستدعاء هي نفسها الموجودة في هذا الدرس. حيث استخدمنا التابع StartTimer من الصنف Device لهذا الغرض (انظر السطر 15). لاحظ الحقل isUpDirection من النوع bool المصرّح عنه في السطر 8. يُفيد هذا الحقل في الاحتفاظ بالاتجاه الحالي للمربّعات أثناء الحركة (أي هل الحركة نحو الأعلى أم نحو الأسفل). يبدأ التابع UpdatePositions بالتصريح عن المتغيّر rect من النوع Rectangle (السطر 20). و Rectangle هو عبارة عن بنية struct أي هو من نوع قيمة value type. يُفيد هذا النوع في وصف الأشكال المستطيلة عمومًا. فهو يمتلك أربع خصائص تصف حجم وموضع أيّ مستطيل على الشاشة. هذه الخصائص هي: X و Y و Width و Height وهي تصف على الترتيب: مقدار الإزاحة الأفقيّة عن الحد الأيسر، مقدار الإزاحة الرأسيّة عن الحد الأعلى، وعرض المستطيل، وارتفاع المستطيل. وذلك بمنطق مشابه لما ورد ذكره في الشكل الأوّل الذي تعرضنا له في هذا الدرس. نقوم في السطر 22 بالحصول على المستطيل (المربّع في واقع الأمر) الحاضن للعنصر boxAccent وهو المربّع الأوّل. ثمّ نختبر كون الإحداثي Y له قد أوشك أن يصبح سالبًا وذلك في السطر 23. فإن أوشك على ذلك فهذا يعني أنّ المربّع boxAccent قد ارتطم بالحد الأعلى للشاشة ويجب تغيير اتجاه الحركة ليصبح نحو الأسفل بدلًا من الأعلى، وهذا ما نفعله في السطر 25. نفس المنطق السابق نطبّقه على العنصر boxGreen وهو المربّع الثالث، وذلك في السطر 28. حيث نحصل على المستطيل الحاضن للعنصر boxGreen. ثمّ نختبر كون الحافة السفلى له (تأمل التعبير rect.Y + rect.Height + 10) قد أوشكت أن تتجاوز قيمتها ارتفاع الصفحة (وهو يماثل في مثالنا الارتفاع الكامل للمخطّط المطلق) وذلك في السطر 29. فإن أوشكت على ذلك فهذا يعني أنّ المربّع boxGreen سيتجاوز الحد السفلي للشاشة ويجب تغيير اتجاه الحركة ليصبح نحو الأعلى بدلًا من الأسفل، وهذا ما نفعله في السطر 31. بعد ذلك ننشئ المصفوفة boxViews بحيث تحتوي على عناصر المربّعات الثلاثة boxAccent و boxRed و boxGreen وذلك في السطر 34. ثمّ يدخل البرنامج حلقة for (الأسطر من 36 حتى 50) التي تنحصر وظيفتها في تحديث إحداثيات المربّعات الثلاثة بحيث تحرّكها نحو الأعلى أو نحو الأسفل بحسب قيمة الحقل isUpDirection. سيكون مقدار الانتقال الرأسي 10 وحدات في كل مرّة كما هو واضح في السطرين 42 و 46. ويتم إسناد الإحداثيّات الجديدة للمربّعات الثلاثة عن طريق استدعاء التابع الساكن AbsoluteLayout.SetLayoutBounds في السطر 49. حيث يتطلّب هذا التابع وسيطين. الأوّل هو المربّع المراد تطبيق الإحداثيات الجديدة عليه وهو موجود ضمن المصفوفة boxView، والثاني هو قيمة من النوع Rectange تحوي المستطيل (المربّع في مثالنا هذا) الحاضن الجديد. الخلاصة تحدثنا في هذا الدرس عن المخطّط المطلق Absolute Layout وكيفيّة استخدامه من خلال رماز XAML. يفيد هذا المخطّط كما أشرنا في التحكّم بحجم وتموضع أي عنصر مرئي على الشاشة على نحو دقيق. تناولنا تطبيقين بسيطين يوضّحان كيفيّة التحكّم بحجم وموضع كل عنصر من عناصر BoxView، كما استخدمنا التابع StartTimer من الصنف Device لتوليد استدعاءات تلقائيّة ذات أزمنة منتظمة إلى تابع مخصّص كي يتحكّم بمواضع هذه العناصر. سنتناول في الدرس القادم تطبيقًا عمليًّا هو في واقع الأمر تحديث للتطبيق الثاني في هذا الدرس لكي نتحكّم في مواضع العناصر بشكل مخصّص أكثر.
  17. مما لا شكّ فيه أنّ نظام التشغيل ويندوز 10 هو من أفضل أنظمة التشغيل التي أنتجتها مايكروسوفت حتى الآن. وعلى الرغم من أنّه ليس من الضروري أن يكون آخر نظام تشغيل تنتجه مايكروسوفت هو الأفضل دومًا (وهناك عدّة أمثلة على ذلك)، إلّا أنّ ويندوز 10 بحق هو نظام تشغيل يستحقّ أن تنتقل إليه. سنتناول في سلسلة من المقالات حول ويندوز 10 أساسيّات التعامل مع هذا النظام، بالإضافة إلى استكشاف العديد من خصائصه المفيدة والمهمّة بنفس الوقت. سنستهل هذه السلسلة بالحديث عن إصدارين محدّدين من ويندوز 10، حيث سنقارن بينهما من حيث بعض المزايا بالإضافة إلى السعر الحالي لكلّ منهما. كما سنتحدّث عن الترقية من نظام تشغيل أقدم إلى ويندوز 10، أو تنصيب نسخة جديدة تمامًا، حيث سنتحدّث بشيء من التفصيل عن كيفيّة تنصيب ويندوز 10 على الحاسوب الشخصي في المقال القادم. ما الذي يُقدّمه لي ويندوز 10؟ سيقدّم لك ويندوز 10 العديد من المزايا الجديدة والمحسّنة، والتي سنتحدّث عنها تباعًا من خلال هذه السلسلة. إليك بعضًا من هذه المزايا: المساعد الشخصي كورتانا Cortana وهو من أبرز هذه المزايا، رغم أنّ النسخة العربية من ويندوز 10 لا تدعمه حتى لحظة كتابة هذا المقال (توجد خطط لدعمه في المستقبل القريب). أسطح المكتب الافتراضيّة virtual desktops وعارض المهام Task View. وهما ميّزتان متكاملتان تسمحان لنا بمزيد من التنظيم في العمل في ويندوز 10. مركز الصيانة Action Center. يمكن من خلاله الوصول إلى أيّة إشعارات جديدة من نظام التشغيل، أو إشعارات رسائل بريد إلكتروني جديدة (في حال استخدمت تطبيق البريد الذي يأتي مع ويندوز)، كما يمكنك الوصول من خلال هذا المركز إلى إعدادات الحاسوب المختلفة، كما ويمكن التحكّم السريع باتصالات الشبكة اللاسلكيّة Wi-Fi بالإضافة إلى العديد من الإمكانيّات الأخرى. تحسينات كبيرة على البرمجيّات المرفقة مع نظام التشغيل مثل تطبيق البريد الافتراضي، وتطبيق التقويم. لهواة الألعاب هناك تطبيق Xbox مُضمّن في ويندوز 10 يسمح للمستخدم استعراض الألعاب التي يلعبها مع إمكانية مراجعة التعليقات التي وضعها اللاعبون الآخرون، بالإضافة إلى إمكانيّة إضافة دعوة لصديق للعب إحدى الألعاب وغيرها من المزايا. إلّا أنّ أهمّها هو إمكانيّة الاتصال بجهاز Xbox حقيقي، والاستمتاع بلعب ألعابك المفضّلة عن طريق حاسوبك الشخصي الذي يُشغّل ويندوز 10. حيث يتمّ تبادل البيانات بين الحاسوب وجهاز Xbox عن طريق الشبكة المحليّة. إصدارات ويندوز 10 لويندوز 10 عدّة إصدارات وهي: - الإصدار المنزلي Windows 10 Home Edition. - الإصدار الاحترافي Windows 10 Pro Edition. - الإصدار المؤسّساتي Windows 10 Enterprise Edition. - الإصدار التعليمي Windows 10 Education Edition. - إصدار الأجهزة المحمولة Windows 10 Mobile. سنتحدّث في هذه السلسلة بشكل أساسيّ عن الإصدار Windows 10 Pro. يحتوي الإصدار Windows 10 Pro بكلّ تأكيد على جميع المزايا الموجودة في Windows 10 Home بالإضافة إلى مزايا أخرى إضافيّة تناسب عالم الأعمال. يبيّن الجدول التالي بعضًا من أبرز أوجه الاختلاف بين هذين الإصدارين: وهناك اختلاف في السعر بطبيعة الحال، فحتى لحظة كتابة هذا المقال، يبلغ سعر نسخة Home في متجر الولايات المتحدّة ما يقارب 120 دولار. ويبلغ سعر نسخة Pro في نفس المتجر 200 دولار تقريبًا. أمّا بالنسبة للنسخ المخصّصة للشرق الأوسط فهناك تباين واضح بالأسعار حتى بالنسبة للدول العربيّة المتجاورة. قارن بين سعر متجر المملكة العربيّة السعوديّة ووسعر متجر الإمارات العربيّة المتحدّة. هل أختار الترقيّة أم النسخة الجديدة؟ في كلتا الحالتين ستدفع ثمن النسخة كاملةً. ولكن يُعتبر خيار الترقية Upgrade أسهل من ناحية الإجراءات المتّبعة لتثبيت ويندوز 10. وينبغي هنا الانتباه في حالة الترقية إلى نوع نسخة الويندوز التي لديك، هل هي 64 بت أم 32 بت. كما ينبغي أن تنتبه إلى اللغة الحالية المستخدمة في نظام التشغيل قبل الترقية. بالنسبة إليّ فأنا أفضّل النسخة الجديدة. فأنت تنصّب نسخة نظيفة من نظام التشغيل، ودون الحاجة إلى أيّة اعتبارات أخرى باستثناء المتطلّبات الحاسوبيّة الدنيا التي سنتكلّم عنها في الفقرة التالية. المتطلّبات الحاسوبيّة الدنيا لتشغيل ويندوز 10 يتطلّب حاسوبك أن يمتلك المواصفات العتاديّة التالية على أقلّ تقدير كي يتمكّن من تشغيل ويندوز 10: معالج ذو سرعة لا تقل عن 1 جيجا هرتز. ذاكرة وصول عشوائيّة RAM لا تقل عن 1 جيجا بايت لنسخة 32 بت. ولا تقل عن 2 جيجا بايت لنسخة 64 بت من ويندوز 10. مساحة خالية على القرص الصلب لا تقل عن 16 جيجا بايت. بطاقة عرض رسوميّة تدعم DirectX 9. هذه هي المواصفات الأقل. وكلّما كان حاسوبك يمتلك مواصفات أعلى من المواصفات المذكورة كان أدائه أفضل بالطبع. وعلى أيّة حال، إذا كنت تستخدم أصلًا نظاميّ التشغيل Windows 8.1 أو Windows 8 فعلى الغالب أنّك لن تعاني أيّة مشاكل عند الانتقال إلى Windows 10. الخلاصة من المؤكّد أنّ ويندوز 10 من بين أكثر أنظمة التشغيل تميُّزًا التي أطلقتها مايكروسوفت خلال تاريخها. لقد تعلّمت مايكروسوفت الكثير من أخطائها السابقة، حيث تلافت الكثير من الانتقادات التي كانت تُوجّه عادةً إلى أنظمة التشغيل الأقدم. في الحقيقة يخضع ويندوز 10 للتطوير المستمرّ، وهناك تحديثات مستمرّة تختلف بطبيعتها عن تلك التحديثات الروتينيّة التي كانت تجري لأنظمة تشغيلها السابقة. على أيّة حال، أرجو أن تستمتع بهذه السلسلة من المقالات التي تكشف العديد من المزايا الجديدة والمفيدة في ويندوز 10.
  18. سنتناول في هذا الدرس من سلسلة تعلّم برمجة تطبيقات أندرويد باستخدام Xamarin.Forms تطبيقًا عمليًّا مفيدًا آخرًا، نتعلّم من خلاله المزيد عن مزايا مخطّط الشبكة Grid Layout واستخداماته العمليّة في التطبيقات التي نطوّرها. سيستخدم هذا التطبيق مخطّطًا تكراريًّا Histogram سيكون مصمّمًا باستخدام مخطّط الشبكة. إذا أردت معرفة المزيد عن مخطّط الشبكة فيمكنك مراجعة هذا الدرس. وإلّا، فيمكنك البدء مباشرةً في هذا الدرس. فكرة التطبيق تتلخّص فكرة هذا التطبيق في أنّ المستخدم سيُدخل نصًّا بأيّ لغة يرغبها. ثم ينقر على زر "احسب" ليعمل التطبيق بعد ذلك على حساب تكرار كلّ محرف من محارف النص المُدخل. بعد الانتهاء من ذلك، سيعمل التطبيق على إظهار مخطّط تكراري Histogram على شكل مخطّط أعمدة bars chart يمكن من خلاله ملاحظة الأحرف الأكثر تكرارًا والأقل تكرارًا من نظرة واحدة. سيعتمد التطبيق على عنصر رسومي من النوع Editor لاستقبال الدخل النصيّ من المستخدم. وكذلك على عنصر الزر Button للبدء بإيجاد القيم التكراريّة، وأيضًا سيستخدم مخطط شبكة لعرض النتائج التكراريّة. من أجل كل حرف موجود في النص، سيضيف التطبيق عمود bar سيكون عبارة عن عنصر BoxView يكون ارتفاعه متناسبًا مع تكرار الحرف ضمن النص المُدخَل. بعد إظهار مخطّط الأعمدة سيكون من الممكن النقر على أي عمود (عنصر BoxView) ليعرض التطبيق رسالة للمستخدم تحوي الحرف الذي يمثّله هذا العمود مع عدد مرًّات تكراره ضمن النص المُدخَل. أي بشكل مشابه لما يلي: سنتناول في الفقرة التالية كامل الشيفرة البرمجيّة لهذا التطبيق. الشيفرة البرمجيّة للتطبيق ابدأ بإنشاء مشروع جديد من النوع Blank App (Xamarin.Forms Portable) وسمّه GridBarChart، ثم أبق فقط على المشروعين GridBarChart (Portable) و GridBarChart.Droid كما وسبق أن فعلنا في هذا الدرس. بعد ذلك سنضيف صفحة محتوى تعتمد على رماز XAML كما وسبق أن فعلنا في هذا الدرس سنسمّها GridBarChartPage. احرص على أن تكون محتويات هذه الصفحة على الشكل التالي: 1 <?xml version="1.0" encoding="utf-8" ?> 2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 4 x:Class="GridBarChart.GridBarChartPage"> 5 <StackLayout> 6 <StackLayout VerticalOptions="Start"> 7 <Label Text="تطبيق حساب تكرار المحارف" 8 HorizontalOptions="CenterAndExpand" 9 HorizontalTextAlignment="Center" 10 FontSize="Large" 11 TextColor="Green"/> 12 <Editor x:Name="txtInput" /> 13 <Button x:Name="btnCalculate" 14 Text="احسب" 15 HorizontalOptions="FillAndExpand" 16 Clicked="btnCalculate_Clicked" /> 17 </StackLayout> 18 19 <Grid x:Name="grdLettersHistogram" 20 VerticalOptions="FillAndExpand" 21 BackgroundColor="#EBF2F5" 22 Padding="5,5,5,0"> 23 </Grid> 24 </StackLayout> 25 </ContentPage> من الملاحظ أنّ رماز XAML لهذا التطبيق صغير نسبيًّا. يبدأ الرماز بتعريف مخطّط مكدّس StackLayout سيعمل على احتواء كامل واجهة التطبيق. سيحتوي مخطّط المكدّس هذا على عنصرين آخرين: العنصر الأوّل عبارة عن مخطّط مكدّس آخر (الأسطر من 6 حتى 17) يحتوي على لصيقة تعريفيّة بالتطبيق، وعلى عنصر الإدخال النصيّ Editor الذي أسميته txtInput وهو يسمح بكتابة أكثر من سطر نصيّ واحد ضمنه، بالإضافة إلى زر البدء بالحساب الذي أسميته btnCalculate والذي سيؤدّي نقره إلى الانتقال إلى معالج حدث النقر btnCalculate_Clicked. المعالج السابق سيكون بالتأكيد ضمن ملف الشيفرة البرمجيّة الذي سنطّلع عليه بعد قليل. العنصر الثاني هو مخطّط الشبكة (الأسطر من 19 حتى 23) والذي أسميته grdLettersHistogram. لاحظ أنّ هذا المخطّط لا يحوي حاليًّا أيّة عناصر. سنضيف لاحقًا إلى هذا المخطّط عناصر BoxView يمثّل كل منها محرفًا موجودًا ضمن النص المُدخَل، وذلك عن طريق الشيفرة البرمجيّة كما سنرى بعد قليل. انتقل الآن إلى الملف GridBarChartPage.xaml.cs وهو ملف الشيفرة البرمجيّة التابع لملف رماز XAML السابق. احرص على أن تكون محتوياته على الشكل التالي: 1 using System; 2 using System.Collections.Generic; 3 using Xamarin.Forms; 4 5 namespace GridBarChart 6 { 7 public partial class GridBarChartPage : ContentPage 8 { 9 public GridBarChartPage() 10 { 11 InitializeComponent(); 12 } 13 14 private void btnCalculate_Clicked(object sender, EventArgs e) 15 { 16 Dictionary<char, int> freq = new Dictionary<char, int>(); 17 List<View> bars = new List<View>(); 18 TapGestureRecognizer tapGesture = new TapGestureRecognizer(); 19 int maxFreq = -1; 20 21 tapGesture.Tapped += TapGesture_Tapped; 22 23 string s = txtInput.Text; 24 25 foreach (char t in s) 26 { 27 if (char.IsLetterOrDigit(t)) 28 { 29 if (!freq.ContainsKey(t)) 30 { 31 freq.Add(t, 1); 32 } 33 else 34 { 35 freq[t] = ++freq[t]; 36 } 37 } 38 } 39 40 grdLettersHistogram.Children.Clear(); 41 42 //find the max letter frequency. 43 foreach(var v in freq.Values) 44 { 45 if(maxFreq< v) 46 { 47 maxFreq = v; 48 } 49 } 50 51 //calculate measurment unit will apply on bars. 52 double measureUnit = grdLettersHistogram.Height / maxFreq; 53 54 foreach (var c in freq.Keys) 55 { 56 var boxView = new BoxView 57 { 58 HeightRequest = measureUnit * freq[c], 59 BackgroundColor = Color.Accent, 60 VerticalOptions = LayoutOptions.End, 61 StyleId = string.Format("المحرف '{0}' له التكرار {1}", c, freq[c]), 62 }; 63 64 boxView.GestureRecognizers.Add(tapGesture); 65 66 bars.Add(boxView); 67 } 68 69 grdLettersHistogram.Children.AddHorizontal(bars); 70 } 71 72 private void TapGesture_Tapped(object sender, EventArgs e) 73 { 74 DisplayAlert("رسالة", ((BoxView)sender).StyleId, "اغلاق"); 75 } 76 } 77 } تكمن معظم الشيفرة البرمجيّة في هذا الملف ضمن معالج حدث نقر زر حساب التكرارات btnCalculate_Clicked الذي يمتد من السطر 14 حتى السطر 70. في البداية تمّ تعريف المتغيّر freq في السطر 16 ليكون من النوع العمومي Dictionary، وهو عبارة عن بنية معطيات مشهورة تُعرف بالقاموس dictionary. سيحتوي هذا المتغيّر على جميع الأحرف المختلفة الموجودة ضمن النص المُدخَل بالإضافة إلى عدد مرّات التكرار لكلّ حرف. أمّا في السطر 17 فقد تمّ تعريف المتغيّر bars وهو من نوع القائمة List. سيحتوي هذا المتغيّر على جميع عناصر BoxView التي سننشئها لاحقًا من الشيفرة البرمجيّة. بعد ذلك نعرّف المتغيّر tapGesture وهو من النوع TapGestureRecognizer. سنتمكّن من خلال هذا المتغيّر أن نُكسِب لأي عنصر BoxView إمكانيّة أن ينقر عليه المستخدم ليعرض عند ذلك الرسالة التي تحدثنا عنها مسبقًا. أمّا في السطر 19 فقد عرّفنا المتغيّر maxFreq الذي سيحوي التكرار الأكبر من بين الحروف المختلفة.,> ,> نعمل في السطر 21 على إضافة معالج الحدث TapGesture_Tapped (مصرّح عنه في الأسطر من 72 حتى 75) لحدث النقر Tapped للكائن tapGesture. بعد أن نحصل على دخل المستخدم ونضعه ضمن المتغيّر s في السطر 23، سندخل حلقة foreach التكراريّة بحيث نقرأ محتويات النص s محرفًا تلو الآخر، ونختبر كون هذا المحرف هو حرف أو رقم في السطر 27 لأنّنا لا نريد قبول الفراغات على سبيل المثال. في السطر 29 سنختبر في حال كان هذا المحرف موجود فعلًا ضمن القاموس freq من قبل أم لا وذلك عن طريق التابع ContainsKey. فإن كان غير موجود من قبل، سنعمل على إضافته في السطر 31، أمّا إذا كان موجود من قبل فسنعمل على إضافة التكرار الخاص به بمقدار واحد وذلك في السطر 35: freq[t] = ++freq[t]; لاحظ أنّ التعبير freq[t] يسمح لنا بالوصول إلى قيمة المفتاح t الموجودة في القاموس freq. بعد ذلك سنمسح محتويات مخطّط الشبكة في السطر 40، ثم سننتقل إلى حلقة foreach أخرى (الأسطر من 43 حتى 49) تسمح لنا بحساب التكرار الأكبر من بين المحارف الموجودة ضمن القاموس freq. في السطر 52 سنقوم بإجراء عمليّة حسابيّة بسيطة، حيث سنعمل على حساب واحدة القياس الخاصّة بالأعمدة (عناصر BoxView)، وبشكل أدق، واحدة القياس الخاصّة بارتفاع كل عنصر BoxView. وذلك من خلال تقسيم ارتفاع مخطّط الشبكة grdLettersHistogram على التكرار الأكبر maxFreq الذي حسبناه قبل قليل. سنخزّن واحدة القياس هذه ضمن المتغيّر measureUnit كما هو واضح. سندخل أخيرًا ضمن حلقة foreach أخرى (الأسطر من 54 حتى 67) وظيفتها إنشاء عناصر BoxView كلّ منها يمثّل محرف مختلف موجود ضمن القاموس freq، وبارتفاع يتناسب مع تكرار هذا المحرف ضمن النص المُدخل. ستعمل هذه الحلقة على إضافة كل عنصر BoxView إلى القائمة bars (السطر 66). تجدر الملاحظة أنّنا في السطر 61 قد أسندنا نصًّا توضيحيًّا إلى الخاصيّة StyleId لعنصر BoxView. يحتوي هذا النص على الحرف وعلى تكراره ضمن النص المُدخَل. في الواقع يمكننا دومًا استخدام الخاصيّة StyleId مع أيّ عنصر يرث من الصنف View لمثل هذه الأغراض. في النهاية سنعمل على إضافة الأعمدة (عناصر BoxView) الموجودة ضمن القائمة bars دفعةً واحدةً إلى مخطّط الشبكة من خلال العبارة التالي الموجودة في السطر 69: grdLettersHistogram.Children.AddHorizontal(bars); يعمل التابع AddHorizontal من الخاصّية Children لمخطّط الشبكة على إضافة عنصر أو مجموعة من العناصر (كما في مثالنا) إلى مخطّط الشبكة على أن تكون على نفس السطر (أفقيًّا horizontal) وذلك دفعةً واحدةً. يوجد في الواقع تابع آخر مماثل لهذا التابع وهو التابع AddVertical، ولكنّه يضيف العناصر على نفس العمود. من الممكن تحديد السطر أو العمود المراد الإضافة إليه عن طريق توابع ساكنة static مثل Grid.SetRow و Grid.SetColumn ولكنّنا لن نحتاج إلى مثل هذه التوابع لأنّنا سنترك الإعدادات الافتراضيّة كما هي. بقي أن نتحدّث عن معالج حدث النقر TapGesture_Tapped. في الحقيقة الشيء الوحيد الذي يفعله هذا الحدث هو إظهار رسالة تنبيه للمستخدم (السطر 74) عند نقره لأحد الأعمدة ضمن المخطّط (عنصر BoxView) تحتوي هذه الرسالة على النص الذي مرّرناه مسبقًا لعنصر BoxView ضمن الخاصيّة StyleId له. انتقل الآن إلى الملف App.cs واحرص على أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new GridBarChartPage(); } نفّذ البرنامج وأجر بعض الإدخالات النصيّة، وراقب النتائج. حاول نقر بعض الأعمدة لتظهر لك رسالة المعلومات حوله. الخلاصة تناولنا في هذا الدرس تطبيقًا عمليًّا مفيدًا في حساب التكرارات للأحرف ضمن نص ما، ومن ثمّ عرضها بشكل مخطّط تكراري histogram ضمن مخطّط الشبكة. يوضّح لنا هذا التطبيق مدى القوّة والمرونة التي من الممكن الحصول عليها من استخدام مخطّط الشبكة، هذا بالإضافة إلى إمكانيّة المزج بين استخدام مخطّط الشبكة ومخطّط المكدّس بكلّ سهولة ويسر. هناك الكثير من التطبيقات التي يمكن استخدام مخطّط الشبكة معها. وسنعمل في الدروس القادمة على استخدامه بشكل متكرّر في التطبيقات التي نطوّرها.
  19. سنتناول في هذا الدرس من سلسلة تعلّم برمجة تطبيقات أندرويد باستخدام Xamarin.Forms تطبيقًا عمليًّا مفيدًا حول التعامل مع مخطّط الشبكة Grid Layout وهو عبارة عن تطبيق لوحة أرقام يمكن تطويرها لاحقًا لتصبح مثلًا تطبيق آلة حاسبة متعدّد الوظائف. اطلعنا في الدرس السابق على مخطّط الشبكة وتعلمنا بعض المبادئ الأساسيّة لاستخدامه. يمكنك مراجعة ذلك الدرس، أو من الممكن أن تبدأ مباشرةً في هذا الدرس. فكرة التطبيق سنعمل على كتابة تطبيق لوحة أرقام بسيط، حيث ستظهر أزرار تحمل الأرقام من 0 حتى 9 بالإضافة إلى زر الفاصلة العشرية، مع وجود زر لإلغاء آخر رقم تمّت كتابته. ستبدو واجهة التطبيق كما في الشكل التالي: عندما ينقر المستخدم على أزرار الأرقام ستظهر هذه الأرقام تباعًا بجوار بعضها بالترتيب. أمّا عندما ينقر زر الإلغاء فسيتم إلغاء آخر رقم تمّ نقره. لنستعرض الشيفرة البرمجيّة لهذا التطبيق في الفقرة التالية. الشيفرة البرمجيّة للتطبيق ابدأ بإنشاء مشروع جديد من النوع Blank App (Xamarin.Forms Portable) وسمّه KeypadGrid، ثم أبق فقط على المشروعين KeypadGrid (Portable) و KeypadGrid.Droid كما وسبق أن فعلنا في هذا الدرس. بعد ذلك سنضيف صفحة محتوى تعتمد على رُماز XAML كما وسبق أن فعلنا في هذا الدرس سنسمّها KeypadGridPage. احرص على أن تكون محتويات هذه الصفحة على الشكل التالي: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="KeypadGrid.KeypadGridPage"> <Grid RowSpacing="2" ColumnSpacing="2" VerticalOptions="Center" HorizontalOptions="Center" WidthRequest="180" Grid.HeightRequest="300"> <Label x:Name="displayLabel" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="Large" LineBreakMode="HeadTruncation" VerticalOptions="Center" HorizontalTextAlignment="End" /> <Button x:Name="btnBackspace" Text="⇦" Grid.Row="0" Grid.Column="2" IsEnabled="False" Clicked="btnBackspace_Clicked" /> <Button Text="7" StyleId="7" Grid.Row="1" Grid.Column="0" Clicked="OnDigitButtonClicked" /> <Button Text="8" StyleId="8" Grid.Row="1" Grid.Column="1" Clicked="OnDigitButtonClicked" /> <Button Text="9" StyleId="9" Grid.Row="1" Grid.Column="2" Clicked="OnDigitButtonClicked" /> <Button Text="4" StyleId="4" Grid.Row="2" Grid.Column="0" Clicked="OnDigitButtonClicked" /> <Button Text="5" StyleId="5" Grid.Row="2" Grid.Column="1" Clicked="OnDigitButtonClicked" /> <Button Text="6" StyleId="6" Grid.Row="2" Grid.Column="2" Clicked="OnDigitButtonClicked" /> <Button Text="1" StyleId="1" Grid.Row="3" Grid.Column="0" Clicked="OnDigitButtonClicked" /> <Button Text="2" StyleId="2" Grid.Row="3" Grid.Column="1" Clicked="OnDigitButtonClicked" /> <Button Text="3" StyleId="3" Grid.Row="3" Grid.Column="2" Clicked="OnDigitButtonClicked" /> <Button Text="0" StyleId="0" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Clicked="OnDigitButtonClicked" /> <Button Text="." StyleId="." Grid.Row="4" Grid.Column="2" Clicked="OnDigitButtonClicked" /> </Grid> </ContentPage> من السهل فهم الرُماز السابق مع بعض الملاحظات البسيطة: في البداية لاحظ أنّنا قد أسندنا خصائص إضافيّة لمخطّط الشبكة مثل تباعد الأسطر RowSpacing وتباعد الأعمدة ColumnSpacing وذلك بهدف جعل الأزرار غير ملتصقة ببعضها البعض. كما أسندنا الخيارات الرأسية VerticalOptions والأفقية HorizontalOptions لكي تحمل كل منهما القيمة Center بهدف جعل الشبكة تظهر في مركز الشاشة. لم نستخدم في هذا التطبيق الخاصيّتين RowDefinitions و ColumnDefinitions اللّتان تحدثنا عنهما في الدرس السابق. إذ أنّه من الممكن اعتماد الإعدادات الافتراضيّة الخاصّة بهما، والبدء مباشرة بإضافة العناصر المرئيّة، حيث يمكن من خلال هذه العناصر تحديد السطر والعمود للخليّة التي نودّ وضع العنصر ضمنها كما سنرى بعد قليل. اللصيقة الوحيدة الموجودة في هذا التطبيق تُستَخدم لعرض الرقم الذي أدخله المستخدم. لاحظ أنّنا نريد عرضها في الخلية المحدّدة بالسطر الأوّل والعمود الأوّل، بالإضافة إلى الانتشار لعمودين متتاليين بسبب وجود الخصائص التالية: Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2". كما توجد خاصية أخرى ملفتة للنظر لهذه اللصيقة، وهي الخاصيّة LineBreakMode والتي تحمل القيمة HeadTruncation. هذه القيمة مفيدة في مثل هذه التطبيقات حيث يؤدّي وجودها إلى اقتطاع النص الذي تمّ إدخاله أولًا في حال لم تتسع اللصيقة لعرض كامل النص (يمكنك تجريب ذلك بنفسك فيما بعد). الزر الأوّل الذي يأتي بعد تعريف اللصيقة هو زر إلغاء آخر رقم مُدخل، واسمه btnBackspace، وهو مرتبط مع معالج حدث النقر btnBackspace_Clicked الموجود ضمن ملف الشيفرة البرمجيّة كما سنرى بعد قليل. بالنسبة لبقيّة الأزرار فأمرها بسيط. فكلّ زر نُعيّن له الخاصيّة StyleId للاحتفاظ بالقيمة النصيّة الموافقة للرقم الذي يحمله، فمثًلا الزر الذي يُعبّر عن الرقم 9 ستكون قيمة StyleId له تساوي "9"، وهكذا. الجدير بالملاحظة هنا أننا قد ربطنا جميع هذه الأزرار بنفس معالج الحدث وهو OnDigitButtonClicked، وهو أمر جائز تمامًا، بل ومن المفضّل القيام به. سنطّلع على هذا المعالج بعد قليل. انتقل الآن إلى ملف الشيفرة البرمجيّة KeypadGridPage.xaml.cs الموافق لملف الرُماز السابق، واحرص على أن تكون محتوياته على الشكل التالي: using System; using Xamarin.Forms; namespace KeypadGrid { public partial class KeypadGridPage : ContentPage { public KeypadGridPage() { InitializeComponent(); btnBackspace.IsEnabled = displayLabel.Text != null && displayLabel.Text.Length > 0; } void OnDigitButtonClicked(object sender, EventArgs args) { Button button = (Button)sender; displayLabel.Text += (string)button.StyleId; btnBackspace.IsEnabled = true; } void btnBackspace_Clicked(object sender, EventArgs args) { string text = displayLabel.Text; displayLabel.Text = text.Substring(0, text.Length - 1); btnBackspace.IsEnabled = displayLabel.Text.Length > 0; } } } الشيفرة السابقة بسيطة للغاية، فالصنف KeypadGridPage يحتوي بشكل أساسي على معالجيّ لحدث النقر: المعالج الأوّل هو OnDigitButtonClicked وهو يُستدعى عندما ينقر المستخدم على أحد أزرار الأرقام بالإضافة إلى زر الفاصلة العشرية. وفي هذا المعالج يتم إضافة الرقم الذي نقره المستخدم توًّا إلى محتويات اللصيقة التي تعرض كامل الرقم المُدخَل. نبدأ أولًا بعمليّة تحويل cast للحصول على الزر الذي سبّب استدعاء هذا المعالج: Button button = (Button)sender; ثمّ استخلاص قيمة الخاصيّة StyleId له وضمّها إلى اللصيقة displayLabel: displayLabel.Text += (string)button.StyleId; ومن ثمّ تفعيل زر إلغاء آخر رقم بسبب أنّه قد أصبح هناك رقم واحد على الأقل بشكل مؤكّد ضمن اللصيقة. أمّا المعالج الثاني فهو btnBackspace_Clicked وهو يُستَدعى عندما يتم النقر على زر إلغاء آخر رقم مُدخَل. الشيفرة البرمجيّة ضمن هذا المعالج بسيطة، فهي تعمل أولًا على الحصول على النص الموجود أصلًا ضمن اللصيقة displayLabel وتضعه ضمن المتغيّر النصي text: string text = displayLabel.Text; ومن ثمّ تقوم بحذف آخر رقم عن طريق التابع Substring من المتغيّر text ومن ثمّ إعادة إسناد النص الناتج إلى الخاصيّة Text للصيقة displayLabel. displayLabel.Text = text.Substring(0, text.Length - 1); نقوم في نهاية المطاف بتفعيل زر إلغاء آخر رقم مُدخل أو تعمل على إلغاء تفعيله باستخدام طريقة جميلة تعتمد على تقييم التعبير المنطقي الموجود على يمين عامل الإسناد (=): btnBackspace.IsEnabled = displayLabel.Text.Length > 0; فإذا كانت اللصيقة تحتوي على رقم واحد على الأقل سيكون التعبير displayLabel.Text.Length > 0 مساويًا للقيمة true وبالتالي يتم تفعيل الزر. وإلّا سيعطي هذا التعبير القيمة false ويتم إلغاء تفعيله. حاول إجراء بعض التجارب على هذا التطبيق، ثمّ فكّر كيف يمكن تعديله لإنشاء تطبيق آلة حاسبة فعليّ، يمكنه دعم العمليّات الحسابيّة الأساسيّة الأربع على سبيل المثال. الخلاصة استفدنا من التطبيق الذي تناولناه في هذا الدرس، في كيفيّة استخدام مخطّط الشبكة بشكل عمليّ بغية الاستفادة من مزايا التموضع الدقيقة نسبيًّا التي يوفّرها للعناصر المرئيّة التي تُوضَع ضمنه. سنتابع العمل في الدرس التالي لنبني تطبيقًا عمليًّا مفيدًا أخرًا يستفيد أيضًا من المزايا الرائعة لمخطّط الشبكة في إنشاء مخطّط تكراري إحصائي يشبه مخطّطات الأعمدة التي من الممكن الحصول عليها من تطبيقات مكتبيّة مثل Microsoft Excel مثلًا.
  20. يُعتبر مخطّط الشبكة Grid Layout من المخطّطات الهامّة والضروريّة في تصميم واجهات المستخدم بالنسبة لتطبيقات الأجهزة المحمولة. فيمكن من خلال هذا المخطّط التحكّم على نحو دقيق نسبيًّا بمواقع جميع العناصر المرئيّة الموجودة في الواجهة، وذلك بخلاف مخطّط المكدّس Stack Layout الذي تناولناه منذ بداية هذه السلسلة حتى الآن. حيث كان من الصعوبة التحكّم بمواقع العناصر المرئيّة بشكل دقيق، وخاصةً فيما يتعلّق بالمحاذاة. في الحقيقة يمكن استخدام كل من هذين المخطّطين معًا في الواجهة الواحدة. سنبدأ في هذا الدرس بالتعرّف على مفهوم هذا المخطّط وطريقة استخدامه. ثمّ نُتْبع هذا الدرس بدرسين آخرين يتناولان تطبيقين عمليين لاكتساب الخبرة اللازمة للعمل مع مخطّط الشبكة بسهولة ويسر أكبر. ما هو مخطّط الشبكة؟ مخطّط الشبكة هو عبارة عن بنية تشبه الجدول من الناحية الشكلية ولكنّها تختلف عنه من الناحية العمليّة. فمخطّط الشبكة قد صُمّم بالأساس ليكون وسيلة لتنظيم العناصر المرئيّة ضمن واجهة المستخدم. أمّا الجدول فهو بنية وظيفتها احتواء بيانات يمكن عرضها للمستخدم. سيكون أغلب تعاملنا مع مخطّط الشبكة من خلال رُماز XAML. إذ أنّه من الممكن أيضًا استخدام الأسلوب البرمجيّ في التعامل معه. ولكن التعامل معه من خلال الرُماز أفضل من ناحية الاستخدام والتنظيم. يمكن تعريف مخطّط الشبكة من خلال الوسم . حيث من الممكن تعيين الأسطر rows والأعمدة columns التي يتألّف منها هذا المخطّط من خلال الخاصيّتين RowDefinitions التي تحتوي على تعاريف الأسطر وColumnDefinitions التي تحتوي على تعاريف الأعمدة. يُدعى مكان تقاطع السطر والعمود بالخليّة Cell. الخاصيّة RowDefinitions هي عبارة عن مجموعة collection من العناصر التي يكون كلّ منها من النوع RowDefinition وتعني تعريف سطر. يمكن من خلال هذا النوع ضبط العديد من خصائص هذا السطر. سنهتم حاليًّا بالخاصيّة Height التي تُعبّر عن ارتفاع السطر. من الممكن تعيين قيمة هذا الارتفاع بثلاثة أنواع من المقاييس: النوع الأوّل هو القيمة العدديّة المباشرة وهي قيمة لا تتعلّق لا تتعلّق بالشاشة device-independent units (انظر هذا الدرس). النوع الثاني هو الكلمة Auto، والتي تعني أنّه ينبغي أن يكون ارتفاع السطر مساويًا لأعلى ارتفاع عنصر مرئي موجود ضمنه. النوع الثالث هو النوع النسبيّ، ويُعبّر عنه رمز النجمة (*)، حيث يكون ارتفاع السطر في هذه الحالة بحيث يشغل باقي الارتفاع المتاح لمخطّط الشبكة ككل. ومن الممكن أن يتعلّق أيضًا بسطر آخر له نفس هذا النوع من القياس، وسنوضّح ذلك في مثال تطبيقي بعد قليل. أمّا بالنسبة للخاصيّة ColumnDefinitions هي عبارة عن مجموعة collection من العناصر التي يكون كلّ منها من النوع ColumnDefinition وتعني تعريف عمود. يمكن من خلال هذا النوع ضبط العديد من خصائص هذا العمود. سنهتم بالخاصيّة Width منه التي تُعبّر عن عرض العمود. من الممكن تعيين قيمة هذا العرض كما هو الحال مع تعريف السطر أيضًا بثلاثة أنواع من المقاييس، تماثل من حيث المبدأ الأنواع الثلاثة السابقة من القياس للسطر: النوع الأوّل هنا هو نفسه النوع الأوّل بالنسبة للسطر، وهو قيمة العدديّة المباشرة التي لا تتعلّق لا تتعلّق بالشاشة device-independent units. النوع الثاني هو الكلمة Auto، والتي تعني أنّه ينبغي أن يكون عرض العمود مساويًا لأعرض عنصر مرئي موجود ضمنه. النوع الثالث هو النوع النسبيّ، ويُعبّر عنه رمز النجمة (*) أيضًا، حيث يكون عرض العمود في هذه الحالة بحيث يشغل باقي العرض المتاح لمخطّط الشبكة ككل. ومن الممكن أن يتعلّق أيضًا بعمود آخر له نفس هذا النوع من القياس. وسنوضّح ذلك أيضًا في المثال التطبيقي الذي سنكتبه بعد قليل. من الجدير ذكره أنّه في حالة القياس النسبيّ في كلّ من حالة السطر والعمود، من الممكن وجود رقم بجوار رمز النجمة يدل على الحصّة التناسبيّة للسطر أو للعمود كما سنرى ذلك بعد قليل. تطبيق عملي بسيط باستخدام مخطّط الشبكة ابدأ بإنشاء مشروع جديد من النوع Blank App (Xamarin.Forms Portable) وسمّه SimpleGridApp، ثم أبق فقط على المشروعين SimpleGridApp (Portable) و SimpleGridApp.Droid كما وسبق أن فعلنا في هذا الدرس. بعد ذلك سنضيف صفحة محتوى تعتمد على رُماز XAML كما وسبق أن فعلنا في هذا الدرس سنسمّها SimpleGridPage. احرص على أن تكون محتويات هذه الصفحة على الشكل التالي: 1 <?xml version="1.0" encoding="utf-8" ?> 2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 4 x:Class="SimpleGridApp.SimpleGridPage"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition Height="Auto" /> 8 <RowDefinition Height="100" /> 9 <RowDefinition Height="2*" /> 10 <RowDefinition Height="1*" /> 11 </Grid.RowDefinitions> 12 13 <Grid.ColumnDefinitions> 14 <ColumnDefinition Width="*" /> 15 <ColumnDefinition Width="*" /> 16 </Grid.ColumnDefinitions> 17 18 <Label Text="مخطط الشبكة" 19 Grid.Row="0" Grid.Column="0" 20 FontSize="Large" 21 HorizontalOptions="End" /> 22 23 <Label Text="تجربة مخطط الشبكة" 24 Grid.Row="0" Grid.Column="1" 25 FontSize="Small" 26 HorizontalOptions="End" 27 VerticalOptions="End" /> 28 29 <Image BackgroundColor="Gray" 30 Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Source="icon.png" /> 31 32 <BoxView Color="Green" 33 Grid.Row="2" Grid.Column="0" /> 34 35 <BoxView Color="Red" 36 Grid.Row="2" Grid.Column="1" Grid.RowSpan="2" /> 37 38 <BoxView Color="Blue" 39 Opacity="0.5" 40 Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" /> 41 </Grid> 42 </ContentPage> انتقل الآن إلى الملف App.cs واحرص على أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new SimpleGridPage(); } نفّذ البرنامج لتحصل على شكل شبيه بما يلي: لنحلّل الآن هذا التطبيق البسيط. في البداية أنشأنا مخطّط شبكة عن طريق كتابة الوسم اعتبارًا من السطر 5. بعد ذلك وضعنا تعاريف أسطر الشبكة من السطر 6 حتى السطر 10 على الشكل التالي: <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="100" /> <RowDefinition Height="2*" /> <RowDefinition Height="1*" /> </Grid.RowDefinitions> ويعني ذلك أنّ هذه الشبكة سيكون لها أربعة أسطر (لوجود أربعة وسوم RowDefinition). سيكون ارتفاع السطر الأوّل Auto، ويعني ذلك أنّ هذا السطر سيكون ارتفاعه مساويًا لارتفاع أعلى عنصر موجود ضمنه. أمّا السطر الثاني فارتفاعه 100 وحدة مستقلة عن الجهاز. بالنسبة للسطرين الثالث والرابع فسيكون ارتفاعهما نسبيًّا لوجود رمز النجمة *. لاحظ وجود الرقم 2 بجوار رمز النجمة بالنسبة للسطر الثالث، ووجود الرقم 1 بجوار رمز النجمة بالنسبة للسطر الرابع. الذي سيحدث هنا أنّه وبعد أن يتم تعيين ارتفاعيّ السطرين الأوّل والثاني سيتم اقتسام الارتفاع المتبقي للشبكة بين السطرين الثالث والرابع بحيث تكون حصّة السطر الثالث ضعف (الرقم 2) حصّة السطر الرابع (الرقم 1). بعبارة أخرى ارتفاع السطر الثالث سيكون 2 إلى 1 من ارتفاع السطر الرابع. وضعنا بعد ذلك تعاريف أعمدة الشبكة من السطر 13 حتى السطر 16 على الشكل التالي: <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> من الواضح أنّه سيكون لهذه الشبكة عمودان فقط. كل من هذين العمودين سيكون عرضه نسبيّ (الرمز *). ولكن بسبب عدم وجود أيّ رقم بجوار رمز النجمة في كلّ منهما، سيتمّ اعتبار وجود الرقم 1 بشكل افتراضيّ بجوار كل رمز نجمة (مثل1*). أي بالمحصلة سيكون لكل منهما نفس الرقم، وبالتالي نفس الحصّة النسبيّة لذلك سيكون لهما نفس العرض تمامًا. تأتي بعد ذلك العناصر المرئيّة التي سنضعها ضمن هذه الشبكة. يبدأ ترقيم كل من الأسطر والأعمدة بالرقم صفر. فالسطر رقم صفر هو السطر الأوّل، وكذلك الأمر بالنسبة للأعمدة. إذا نظرت إلى الأسطر من 18 حتى 21 فستجد أنّنا نضيف لصيقة إلى الخليّة المحدّدة بالسطر الأوّل والعمود الأوّل. ويكمن سبب ذلك في السطر 19 حيث نجد الخاصيّتين Grid.Row="0" للسطر رقم 0، وGrid.Column="0" للعمود رقم 0 أيضًا. أي السطر الأوّل والعمود الأوّل. بنفس الأسلوب تمامًا نضيف لصيقة أخرى إلى الخليّة المحدّدة بالسطر الأوّل والعمود الثاني (الأسطر من 23 حتى 27)، وأيضًا عنصر صورة ضمن الخليّة المحدّدة بالسطر الثاني والعمود الأوّل (السطران 29 و30). نلاحظ أيضًا أنّ عنصر الصورة هذا سيشغل بالإضافة إلى العمود الأوّل العمود الثاني أيضًا، وذلك بسبب وجود الخاصيّة Grid.ColumnSpan="2" والتي تشير إلى أنّ الخليّة التي ستحتوي عنصر الصورة يجب أن تمتد على عمودين متتاليين باتجاه اليمين، وهذا ما يُفسّر سبب ظهورها ممتدّة على كامل عرض الشبكة كما هو واضح في الشكل السابق. بعد إضافة عنصر الصورة السابق، سنضيف ثلاثة عناصر BoxView لأغراض العرض فقط (الأسطر من 32 حتى 40). حيث ستشغل هذه العناصر الثلاثة على الترتيب الخلايا المحدّدة بالسطر الثالث والعمود الأوّل، ثم السطر الثالث والعمود الثاني، ثم السطر الرابع والعمود الأوّل. مع ملاحظة أنّ عنصر BoxView الأوسط يحوي الخاصيّة Grid.RowSpan="2" التي تسمح للخلية التي تحتويه بالامتداد إلى سطرين متتاليين. أمّا عنصر BoxView الأخير فيحوي على الخاصية Grid.ColumnSpan="2" لتسمح له بالامتداد على عمودين متتاليين. أي أنّ عنصريّ BoxView الثالث والرابع سيتداخلان في الخليّة المحدّدة بالسطر الرابع والعمود الثاني كما هو واضح من الشكل السابق. الخلاصة تعلّمنا في هذا الدرس كيفيّة التعامل الأساسي مع مخطّط الشبكة Grid Layout. ولعلّ الفهم الأفضل لمثل هذه الأمور تنبع من الممارسّة العمليّة ببناء تطبيقات عمليّة صغيرة ولكنّها مفيدة. سنعمل في الدرسين القادمين على بناء تطبيقين بسيطين يحتويان على العديد من التقنيّات البرمجيّة المفيدة والتي من الممكن استخدامها في التطبيقات الواقعيّة.
  21. انظر هنا: http://www.cplusplus.com/reference/cstring/strcmp/ وهنا: http://www.cplusplus.com/reference/string/string/compare/
  22. سنتابع في هذا الدرس من سلسلة إعداد ماجنتو ما بدأناه في الدرس السابق في عمليّة ضبط بعض الإعدادات الأساسيّة اللازمة للبدء بتشغيل واستخدام ماجنتو. سنعمل في هذا الدرس على ضبط حسابات البريد الإلكتروني القياسيّة التي سيتعامل معها ماجنتو، وأيضًا سنعمل على ضبط العملات المستخدمة، وتحديد أسعار الصرف الخاصّة بها، بالإضافة إلى ضبط موقع العمل الخاص بك. كما جرت به العادة من قبل، عليك أولًا تسجيل الدخول كمدير للنظام عن طريق الرابط http://ubuntu/magento/admin . حسابات البريد الإلكتروني للمتجر Store Email Addresses من الممكن استخدام خمسة عناوين بريد إلكتروني مختلفة بحيث يمثّل كل منها وظيفة مختلفة أو قسم مختلف، بحيث تتوزّع على الشكل التالي: جهة الاتصال العامّة General Contact. ممثّل المبيعات Sales Representative. الدعم الفني Customer Support. بالإضافة إلى بريدين إلكترونيين يمكن تخصيصهما بالشكل الذي تراه مناسبًا. ومن الجدير ذكره أنّه من الممكن ربط أيّ عنوان بريد إلكتروني من العناوين السابقة برسائل مؤتمتة بحيث تظهر كما لو أنّ مرسل هذه الرسائل قد أرسلها من المتجر. قبل أن نبدأ بعمليّة ضبط البريد الإلكتروني، من الضروري تجهيز عناوين بريد إلكتروني خاصّة باسم النطاق الذي تستخدمه. فمثًلا إذا كان عنوان متجرك على الإنترنت هو www.example.com فيجب تحضير عناوين بريد إلكتروني مثل sales@example.com و support@example.com وغيرها. ومن الممكن أن تحصل على مثل هذه العناوين بمراجعة خطة الاستضافة لديك، أو بمراجعة مدير النظام في حال كنت تستضيف ماجنتو على خادوم خاص، مع ملاحظة أنّه من الممكن توفير خدمة مدفوعة لقاء مثل هذه العناوين، وهي بالتأكيد لا تكلّف كثيرًا في حال تعذّر عليك تأمين مثل عناوين البريد الإلكتروني السابقة لسبب أو لآخر (انظر مثلًا إلى هذه الخدمة). يمكننا الآن ضبط عناوين البريد الإلكتروني الخاصّة بالمتجر وذلك باتباع الخطوات التالية: 1- من القائمة الجانبيّة الخاصّة بمدير النظام والتي تظهر في الجهة اليسرى انقر STORES. ستظهر نافذة منبثقة اختر منها التكوين Configuration (تحت بند الإعدادات Settings). 2- اختر من قائمة الخيارات الجانبيّة عناوين البريد الإلكتروني للمتجر Store Email Addresses وهي تحت البند GENERAL. 3- انشر قسم جهة الاتصال العامّة General Contact كما في الشكل التالي: أدخل في حقل اسم المرسل Sender Name اسم الشخص الذي ترغب أن يظهر كمُرسل للرسالة، بحيث يمثّل جهة الاتصال العامّة. أمّا في الحقل Sender Email فأدخل عنوان البريد الإلكتروني للمرسل. كرّر هذه الخطوة من أجل البريد الإلكتروني لممثّل المبيعات Sales Representative، وأيضًا من أجل البريد الإلكتروني للدعم الفني Customer Support، بالإضافة إلى البريدين الإلكترونيين اللذين يمكن تخصيصهما Custom Email 1 و Custom Email 2، وذلك بنشر البند الموافق لكلّ منها. 4- بعد الانتهاء انقر الزر Save Config الموجود في الأعلى. العملات Currencies يدعم ماجنتو استخدام عدد كبير من العملات، حيث يمكنك قبول التسديد بطيف واسع من هذه العملات إن أحببت ذلك. يوجد قسم خاص لإعداد هذه العملات يظهر في الشكل التالي: سنبدأ بإعداد العملات من خلال الخطوات التالية: 1- تأكّد أنّك في صفحة ضبط Configuration ماجنتو، فإن لم تكن كذلك، فمن القائمة الجانبيّة الخاصّة بمدير النظام والتي تظهر في الجهة اليسرى انقر STORES. ستظهر نافذة منبثقة اختر منها ضبط Configuration (تحت بند الإعدادات Settings). 2- اختر من قائمة الخيارات الجانبيّة إعداد العملة Currency Setup الموجود تحت البند GENERAL كما هو واضح من الشكل السابق. 3- انشر بند خيارات العملة Currency Options، لتحصل على شكل شبيه بما يلي: حدّد العملة الرئيسيّة Base Currency التي تودّ استخدامها في التعاملات الماليّة في متجرك. ثمّ حدّد عملة العرض الافتراضيّة Default Display Currency التي تودّ استخدامها لعرض أسعار منتجاتك. أمّا بالنسبة لقائمة العملات المسموحة Allowed Currencies، فمن هنا يمكنك اختيار جميع العملات التي تقبل التعامل بها في متجرك. احرص على اختيار العملة الرئيسيّة، ويمكنك بالطبع اختيار عملات أخرى بالضغط على زر Ctrl أثناء النقر على العملات في القائمة. بعد أن تفرغ يمكنك نقر زر حفظ الإعدادات Save Config. بعد نقر هذا الزر من الممكن أن تحصل على رسالة تطلب منك الانتقال إلى إدارة الذاكرة المخبئيّة Cache Management لإجراء عمليّة تحديث refresh. أغلق هذه الرسالة الآن، سنعمل على حل هذه المشكلة فيما بعد. 4- انتقل إلى قائمة الخيارات الجانبيّة واختر منها CATALOG ثم انقر على البند Catalog لتظهر أمامك الصفحة الموافقة. استخدم شريط التمرير للوصول إلى البند Price. انشر هذا البند وتأكّد من أنّ Catalog Price Scope قد تمّ ضبطه ليكون Global كما في الشكل التالي: انقر زر حفظ الإعدادات Save Config إذا كان ذلك ضروريًّا ثم يمكنك عندها الانتقال إلى صفحة إدارة الذاكرة المخبئيّة ومعالجة المشكلة التي حصلنا عليها قبل قليل، وذلك كما فعلنا في هذا الدرس (انظر الملاحظة آخر الدرس). 5- سنعمل الآن على تحديث نسب التحويل بين العملات، وذلك بالانتقال مجدّدًا إلى القائمة الجانبيّة الخاصّة بمدير النظام والتي تظهر في الجهة اليسرى. انقر STORES، وبعد ذلك اختر نسب التحويل Currency Rates تحت بند العملات Currency. بعد ذلك ومن الصفحة التي ستظهر، انقر على نسبة التحويل التي ترغب بتعديلها، ثم أدخل النسبة المطلوبة. وبعد الانتهاء عليك نقر زر Save Currency Rates. انظر إلى الشكل التالي مع ملاحظة أنّني قد أضفت عملة أخرى وهي الريال السعودي SAR كعملة مسموح التعامل بها، بالإضافة إلى الدولار الأمريكي: لاحظ وجود زر صغير اسمه Import ويعني استيراد. في حال نقرت على هذا الزر سيعمل ماجنتو على جلب سعر الصّرف الخاص بجميع العملات المسموحة لديك من مزوّد الخدمة الموجود فوق زر Import تمامًا، وهو في حالتنا: Yahoo Finance Exchange. 6- بعد الانتهاء يمكنك نقر الزر Save Currency Rates. موقع الشّركة Merchant Location يُعتبر موقع الشّركة ضروريًّا لإحدى مزايا ماجنتو وهي طرق الدفع Payment Methods والتي سنتحدّث عنها في درس لاحق بشكل موسّع أكثر. يُعتبر ضبط موقع الشّركة مهمّة سهلة للغاية فكلّ ما عليك فعله هو اتباع الخطوات البسيطة التالية: سنعود إلى صفحة الضّبط الخاصّة بماجنتو، وذلك من خلال نقر البند STORES الموجود ضمن القائمة الجانبيّة الخاصّة بمدير النظام والتي تظهر في الجهة اليسرى. ستظهر نافذة منبثقة اختر منها الضّبط Configuration (تحت بند الإعدادات Settings). اختر من قائمة الخيارات الجانبيّة طرق الدفع Payment Methods وهي موجودة تحت البند SALES (استخدم شريط التمرير للوصول للأسفل). انشر موقع الشّركة Merchant Location، لتحصل على شكل شبيه بما يلي: اختر الدولة التي تريدها من قائمة Merchant Country. انقر زر حفظ الإعدادات Save Config. الخلاصة تناولنا في هذا الدرس كيفيّة ضبط بقية الإعدادات والخيارات اللازمة للتشغيل الأساسي لماجنتو، حيث تحدّثنا عن كيفيّة ضبط عناوين البريد الإلكتروني Store Email Addresses، والعملات Currencies، وموقع الشّركة Merchant Location. ورغم أنّه توجد العديد من الخيارات الأخرى، إلّا أنّنا سنتناول ما نحتاجه منها تباعًا أثناء تقدّمنا في دروس هذه السلسلة.
  23. كنّا قد رأينا في دروس سابقة كيفيّة الاستفادة من الخصائص الموجودة في عناصر مرئية في التحكّم في خصائص عناصر مرئيّة أخرى كما فعلنا مسبقًا في هذا الدرس حينما استطعنا التحكّم بحجم الخط المستخدم ضمن لصيقة باستخدام خاصيّة القيمة Value لعنصر Slider. حيث استخدمنا لهذا الغرض معالجات أحداث تحوي شيفرة برمجيّة. سنتعلّم في هذا الدرس من سلسلة تعلّم برمجة تطبيقات أندرويد باستخدام Xamarin.Forms. كيفيّة الاستغناء عن استخدام الشيفرة البرمجيّة في مثل هذه المهام. وذلك من خلال استخدام تقنيّة ربط البيانات data bindings التي تقدّمها لنا Xamarin. تفيد هذه التقنيّة في التقليل من كتابة الشيفرة البرمجيّة إلى حدٍّ كبير. حيث يمكننا ربط العناصر المرئيّة مع بعضها مباشرةً دون الحاجة لكتابة أي سطر من الشيفرة. سنتناول في هذا الدرس مثالين بسيطين لتوضيح هذه الفكرة. سنعمل في المثال الأوّل على التحكّم في حجم لصيقة باستخدام عنصر Slider. أمّا في المثال الثاني فسنجري تحسينًا بسيطًا على المثال الأوّل، حيث سنضيف لصيقة أخرى ونربطها مع نفس عنصر المنزلق Slider، بحيث ستعرض هذه اللصيقة الجديدة القيمة الحاليّة للخاصيّة Value للعنصر Slider. تطبيق التحكّم بحجم اللصيقة ابدأ بإنشاء مشروع جديد من النوع Blank App (Xamarin.Forms Portable) وسمّه SimpleDataBindingApp، ثم أبق فقط على المشروعين SimpleDataBindingApp (Portable) و SimpleDataBindingApp.Droid كما وسبق أن فعلنا في هذا الدرس. بعد ذلك سنضيف صفحة محتوى تعتمد على رُماز XAML كما وسبق أن فعلنا في هذا الدرس سنسمّها SimpleDataBindingPage. احرص على أن تكون محتويات هذه الصفحة على الشكل التالي: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleDataBindingApp.SimpleDataBindingPage"> <StackLayout > <StackLayout.Children> <Label x:Name="lblText" VerticalOptions="CenterAndExpand" Text="النص" HorizontalOptions="Center" BindingContext="{x:Reference Name=slider}" Scale="{Binding Path=Value}" /> <Slider x:Name="slider" Maximum="10" Minimum="1" Value="4" VerticalOptions="CenterAndExpand"/> </StackLayout.Children> </StackLayout> </ContentPage> انتقل إلى الملف App.cs واحرص على أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new SimpleDataBindingPage(); } نفّذ البرنامج باستخدام F5 لتحصل على شكل شبيه بما يلي: يمكنك تمرير عنصر المنزلق Slider لترى كيف يتغيّر حجم اللصيقة تلقائيًّا. هناك عدّة نقاط سنتحدّث عنها حول هذا التطبيق البسيط: 1- لم نستخدم الشيفرة البرمجيّة أبدًا. لقد ربطنا الخاصيّة Value لعنصر Slider مع خاصيّة مقياس العنصر Scale للصيقة من خلال رُماز XAML فحسب. 2- في أيّة عمليّة ربط هناك الكائن المصدر source (في مثالنا السابق كان عنصر Slider)، والكائن الهدف target (في مثالنا السابق كان عنصر اللصيقة Label). 3- في مثالنا السابق، ضبطنا الخاصيّة BindingContext للّصيقة (الهدف) لكي تشير إلى عنصر Slider (المصدر)، لاحظ كيف عيّنّا اسم عنصر المنزلق slider وذلك من خلال النص التالي: BindingContext="{x:Reference Name=slider}" ثم أخبرنا Xamarin أنّنا نريد ربط خاصيّة مقياس العنصر Scale للّصيقة مع الخاصيّة Value لعنصر المنزلق Slider عن طريق ضبط النص التالي إلى الخاصيّة Scale للصيقة: Scale="{Binding Path=Value}" تتحكّم الخاصيّة Scale بمقياس العنصر. سنتحدّث عن ذلك في دروس لاحقة ضمن هذه السلسلة. التطبيق المحسّن للتحكّم بحجم اللصيقة أضف إلى التطبيق السابق صفحة محتوى تعتمد على رُماز XAML كما وسبق أن فعلنا في هذا الدرس سنسمّها EnhancedDataBindingPage. احرص على أن تكون محتويات هذه الصفحة على الشكل التالي: <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleDataBindingApp.EnhancedDataBindingPage"> <StackLayout > <StackLayout.Children> <Label x:Name="lblText" VerticalOptions="CenterAndExpand" Text="النص" HorizontalOptions="Center" BindingContext="{x:Reference Name=slider}" Scale="{Binding Path=Value}" /> <Slider x:Name="slider" Maximum="10" Minimum="1" Value="4" VerticalOptions="CenterAndExpand"/> <Label x:Name="lblScale" VerticalOptions="CenterAndExpand" Text="{Binding Path=Value, StringFormat = 'Scale = {0:F1}'}" HorizontalOptions="Center" BindingContext="{x:Reference Name=slider}"/> </StackLayout.Children> </StackLayout> </ContentPage> من الواضح أنّ التعديل الوحيد الملاحظ هنا هو في وجود عنصر اللصيقة الجديد lblScale والذي تنحصر وظيفته كما أوضحنا سابقًا على عرض القيمة الحالية لعنصر المنزلق Slider. إليك تعريف عنصر اللصيقة lblScale: <Label x:Name="lblScale" VerticalOptions="CenterAndExpand" Text="{Binding Path=Value, StringFormat = 'Scale = {0:F1}'}" HorizontalOptions="Center" BindingContext="{x:Reference Name=slider}"/> كما وسبق أن فعلنا مع لصيقة النص lblText، قمنا بتعيين الخاصيّة BindingContext لتشير إلى عنصر المنزلق الذي يحمل الاسم "slider": BindingContext="{x:Reference Name=slider}"/> ثمّ سنربط هذه المرّة الخاصيّة Text لهذه اللصيقة بالخاصيّة Value لعنصر المنزلق على الشكل التالي: Text="{Binding Path=Value, StringFormat = 'Scale = {0:F1}'}" لاحظ كيف أنّ الربط Binding قد جرى بين الخاصيّة Value لعنصر المنزلق، والخاصيّة Text لعنصر اللصيقة الجديد lblScale. لاحظ أيضًا الكلمة الجديدة StringFormat. ستُفسَّر هذه الكلمة في الواقع لتصبح استدعاء إلى التابع String.Format الذي يعمل على تنسيق النص Scale = {0:F1} بحيث يظهر ضمن اللصيقة عدد ذو فاصلة عشرية ثابتة تمتلك رقم واحد فقط على يمين الفاصلة العشريّة. يمكنك تغيير هذا السلوك، بحيث تلغي عمليّة التنسيق هذه لترى الفرق وذلك على الشكل التالي: Text="{Binding Path=Value'}" انتقل الآن إلى الملف App.cs واحرص على أن تكون بانية الصنف App على الشكل التالي: public App() { // The root page of your application MainPage = new EnhancedDataBindingPage(); } عند تنفيذ البرنامج ستحصل على شكل شبيه بما يلي: يمكنك تحريك المنزلق لترى كيف يعمل الربط بين الخاصيّة Value وكل من الخاصيّتين Scale وText للصيقتين الموجودتين في البرنامج. الخلاصة يُعتبر هذا الدرس مثيرًا للانتباه. حيث لم نكتب أي شيفرة برمجيّة في أيّ من التطبيقين اللذين بنيناهما في هذا الدرس. إنّ عمليّة ربط البيانات data bindings بمعزل عن كونها توفّر الوقت والجهد في إنجاز مهام روتينيّة (وهو أمر مهم بالطبع)، تُعتبر حيويةً في أسلوب تصميم التطبيقات MVVM (اختصارًا للكلمات Model View ViewModel) الشائع جدًّا في تصميم تطبيقات الأجهزة المحمولة. سنتناول في الدرس القادم موضوعًا مهمًّا نتعلّم من خلاله كيفيّة تصميم واجهات مستخدم دقيقة من خلال مخطّط الشبكة Grid Layout. وهو أحد أنواع المخطّطات المستخدمة في Xamarin والتي من المؤكّد أنّها ستثير إعجابك.
×
×
  • أضف...