بعد ان تعرفنا على كيفية الوراثة من QWidget و كيفية تقسم البرنامج الى عدة ملفات ،،
فان المرسل هو احد كائنات QLineEdit ، ولنسمه upperCaseLineEdit ، والمستقبل هو الكائن الاخر ولنسمه lowerCaseLineEdit. الكائن الاول سيرسل حدث textChanged والذي يأخذ السلسة التي تم كتابتها فيه كوسيط. ترسل السلسلة المكونة من احرف كبيرة ، الى الكائن الثاني والذي يجب ان ينفذ دالة ما بحيث تودي الغرض . نرجع الى التوثيق ، نبحث عن جميع ال slots ،،، لن نجد ما نريد ! فقط اقرب شيء هو دالة تعيين نص setText . وهذه سوف تقوم بكتابة النص نفسه ! اذا نحتاج الى slot جديد بحيث يحول من الاحرف الكبيرة الى احرف صغيرة ،، وكذلك slot اخر لكي يحول من حرف صغير الى كبير . الشفرة البرمجية : الملف conventor.h:
ملف الرأس conventor.h تم فصله عن التطبيق وذلك لاننا نريد تعريف slots ، كذلك تم الوراثة من الفئة QWidget ، لكي نضمن جميع خصائص اي widget. السطر 6: يحوي اعلان عن فئة QLineEdit ، وذلك لاننا نريد تعريف مؤشر من هذه الفئة . ومن الممكن ان نستبدل هذا الاعلان بعملية تضمين ملف الرأس QLineEdit ، ولكن لان عملية التضمين ستأخذ وقتا من المترجم اثناء قراءة الشفرة ، لذا من الافضل دائما وضع اعلان عن الفئة اذا كنا نريد تعريف مؤشر منها . السطر 10 : هذا السطر يحوي الاعلان عن الماكرو ، وهذه اشارة للمترجم moc بان هذا الملف بحاجة الى ترجمة بواسطته ، النتيجة من عملية الترجمة هو الملف moc_conventor.cpp . السطر 15: يحوي على محدد لم تستعمله من قبل وهو slots . وجميع الدوال المعرفة تحته تعتبر دوال slot ،اي يمكن ان نربطها مع حدث ما في عبارة connect. مستوى حماية المحدد public or private or protected ، لا تاثير لها اذا كنت تستخدم هذه الدوال للربط فقط ، اي في عبارة connect. اما اذا كنت تريد استخدامها كدوال تعين setter ، فيجب الانتباه الى مستوى الحماية. الاسطر 16 و 17 : لدينا دالتين ، الاولى تقوم بكتابة السلسة المررة اليها كأحرف كبيرة في الكائن upperCaseLineEdit. اما الدالة الاخر ، تقوم بكتابة السلسة المررة اليها كأحرف صغيرة في الكائن lowerCaseLineEdit. الاسطر 19 الى 21 : تم وضع المحدد الخاص private وذلك لتعريف الكائنين upperCaseLineEdit و lowerCaseLineEdit. ومن الممكن ان نقوم بتعريف الكائنات في دالة البناء ، ولكن في هذا المثال يجب ان تكون هذه الكائنات موجودة في الفئة نفسها ، وذلك حتى تستطيع جميع الدوال بما فيها ال slots الوصول اليهم. الملف conventor.cpp :
على نفس المنهج المتبع دائما ، حيث نبدأ بانشاء ال widgets ، ثم وضع الخصائص ، ثم الربط ثم انشاء المخططات وتعبئتها بال widgets ، واخيرا وضع المخطط على كائن الفئة. الامر الذي قد يبدو جديدا هذه المرة ، هو في الربط او تأسيس الاتصال .. حيث ان الكائن المستقبل اصبح هو this ، ونعلم ان this هي مؤشر لكائن الفئة . اذا بمعنى اخر ، فان عبارة الربط تقول ، انشيء اتصال بحيث ان المرسل هو upperCaseLineEdit والحدث المرسل هو textEdited ، اما المستقبل هو كائن هذه الفئة ، والدالة التي يجب تنفيذها هي setLower . لاحظ انه يجب ان تتطابق انواع الوسائط في عملية الربط . كذلك انشئ اتصال اخر بين lowerCaseLineEdit ، وكائن هذه الفئة . وبالنسبة للمخطط ، فلم نستخدم لا الافقي والا العمودي ، حيث استخدمنا النوع الشبكي ، وسندرسه لاحقا . نأتي لدالة setUpper ، حيث تستقبل هذه الدالة سلسلة نصية . هدف هذه الدالة هو وضع قيمة للكائن upperCaseLineEdit ، لكن بعكس حالة الاحرف. تستخدم الدالة toUpper والتي ستقوم بعملية التحويل . عمل هذه الدالة واضح جدا ، لكن الشئ الغريب هو وجود شرط يتأكد من ان القيمة المرسلة الى الدالة هل هي نفس قيمة الكائن upperCaseLineEdit !! اذا كان نعم ، فلا يوجد داعي للاكمال ، لان السلسة هي نفسها ولا يوجد اختلاف ! هذا الشرط يلعب دور كبير في عملية المزامنة بين كائنين او اكثر ، حيث بدونه سوف ندخل في حلقة لا نهائية . اما الدالة setLower ، فهي تعمل بنفس فكرة الدالة السابقة ولكن تحول الاحرف من كبير الى صغير. اهم شيء يجب ان تتذكره دائما عند كتابة تعريف اي دالة slots هو شرط التوقف ! حيث بدون هذا الشرط سنقع في مشكلة كبيرة ! انظر الى هذين السطرين لتعرف المشكلة ! ولنأخذ هذا السيناريو ،، نفرض انك قمت بالكتابة على upperCaseLineEdit ، في هذه الحالة سوف 'تبعث' اشارة تدل على وجود تعديل ،، هذا الاشارة قمنا بربطها مع الدالة setLower . وفي حالة عدم وجود الشرط في الدالة setLower فانها ستقوم بتحويل السلسة الى lower case ثم تضع النتيجة في الكائن lowerCaseLineEdit . فورا سيتم 'بعث' اشاره تدل على وجود تعديل في الكائن lowerCaseLineEdit ، وهذه الاشارة قمنا بربطها مع الدالة setUpper. وفي حالة عدم وجود الشرط في الدالة setUpper فانها ستقوم بتحويل السلسلة الى upper case ثم تضع النتيجة في الكائن upperCaseLineEdit . من جديد سيتم ارسال اشاره ......الخ. لذلك لا بد من وجود شرط التأكد في اي دالة slots ، خاصة في حالة التزامن بين الكائنات. الملف main.cpp :
من الان وصاعدا ، لن اذكر اسم الملف main.cpp مرة اخرى . وذلك لان محتوياته اصبحت معروفة جدا ، ولن تتغير الا في حالات نادرة. مجرد تضمين لملف الرأس للفئة التي تم كتابتها ، ثم انشاء كائن منها ، واستدعاء الدالة show. ملاحظة على الشفرة السابقة : يجب ادخال حرف كبير في الكائن الاول ، وحرف صغير في الثاني لكي يعمل بشكل جيد. وكان من الممكن ان اتحكم في نوع الاشياء التي يجب كتابتها عن طريق QValidator. ولكن حتى لا يتغير الموضوع الى موضوع اخر ، ففضلت عدم استخدامه ، وسوف نعود لهذا المثال لاحقا ، عندما ندرس التحكم في المدخلات. نذهب الى المثال الاخر .. ا.هـ |