اهلا بالجميع ،،
حديثنا اليوم سيكون عن كيفية معالجة النصوص داخل مربع النص QTextEdit
اي باختصار كيف نقوم بكتابة نصوص منسقة rich text داخل هذا المربع !!
محتويات الدرس :
- ما هو ال QTextEdit
- ما هو ال QTextDocument
- كيفية ادخال النصوص داخل ال QTextEdit
- ما هو المؤشر Cursor
- كيفية ادخال الجداول tables والاطارات frames والصور images
مشاريع تطبيقية :
- كتابة برنامج محرر نصوص Word Processor
- كتابة فئات لانشاء التقارير او برنامج Reports Builder
الموضوع بشكل كامل يتمحور حول ال QTextEdit,QTextDocument,QTextCursor
لذلك سوف نتناولهم اولا ثم ننتقل الى محتويات درس اليوم
* ملاحظة : جميع الاكواد في هذا الدرس هي اكواد توضيحية Toys Example، يعني ليست مكتوبة بطريقة عملية، والهدف هو لتوضيح الفكرة فقط بأقل عدد من الاسطر.
نبدأ على بركة الله مع QTextEdit ،،
************************
ما هو ال QTextEdit ::
هو عبارة عن اداة widget تستخدم لعرض وتعديل النصوص المنسقة rich text والغير منسقة plain text
ال plain text هي عبارة عن نصوص لا يحوي اي تنسيق مثل الاكواد التي نقوم بكتابتها في اي محرر.
اما ال rich text فهو عبارة عن نصوص منسقة اي تحوي الوان وجداول واطارات وخلفيات و...الخ.
استخدام ال QTextEdit ::
سنبدأ بمثال صغير ، وسنقوم بالتطبيق عليه.
كالعادة يجب ان نعلن اولا عن ملفات الرأس المستخدمة ،، لذلك لا تنسى تضمين الملف :
هنا قمنا بانشاء ال text edit و عرضناها على الشاشة كنافذة مستلقة .
الان قم بالكتابة علي text edit عدة اسطر ،، ولاحظ انه يقوم بانشاء ال scroll bar العمودي عندما تصل الى نهاية المربع.
تجربة بعض الخصائص والدوال ::
يوجد العديد من الخصائص والدوال المهمة لل QTextEdit ،، سنستعرض بعضا منها ::
خاصية لف السطر: اي الانتقال الى السطر الجديد .
الوضع الافتراضي هو WidgetWidth اي ان نهاية السطر تكون على حجم المربع.
يمكنك وضع خاصية لف السطر "الذهاب الى سطر جديد" تكون فقط عند الضغط على انتر كالاتي ::
او يمكن تحديد حجم معين من النقاط pixels كالاتي::
او عدد معين من الحروف لكي يتم بها لف السطر.
الدوال الاكثر استخداما :
append():اضافة نص الى نهاية ال text edit
clear(): حذف كل النص في ال text edit
copy(): نسخ النص المحدد الى ال clipboard
cut(): قص النص المحدد.
paste(): لصق .
undo():الغاء اخر عملية.
redo(): اعادة اخر عملية.
selectAll(): نسخ الكل.
zoomIn(): تكبير النص
zoomOut(): تصغير النص
setAlignment(): وضع المحاذاة.
setFontWeight(): تحديد كثافة الخط
setFontUnderLine():وضع خط تحت النص
setFontPointSize():تحديد حجم النقطة
setCurrentFont():تحديد نوع الخط
setTextColor(): تحديد لون الخط.
setText(): وضع نص.
setPlainText():وضع نص غير منسق
setHtml(): وضع نص HTML
بعض ال SIGNAL ::
copyAvailable(): ترسل "emit" اذا كان هناك قابلية لعمل نسخ.
redoAvailable(): ايضا يتم استدعائها لكن اذا كان هناك قابلية لاعادة اخر عملية.
undoAvailable(): يتم استدعائها اذا كان هناك قابلية للتراجع
textChanged(): ترسل emit اذا حدث اي تغيير في محتويات ال QTextEdit.
اعتقد ان هذه الدوال كافية لعمل محرر نصوص بسيط جدا ،، بحيث لا يحوي جداول ولا صور ولا ..الخ.
راجع ال decumentation لمعرفة جميع الدوال وكذلك ال signals و ال slots.
**********************************
الان نعود مرة اخرى لتعريف ال QTextEdit والتي قلنا انها تستخدم لعرض وتعديل النصوص المنسقة والغير منسقة .
طيب السؤال المطروح الان : اين يتم تخزين النصوص اذا كان ال QTextEdit يستخدم لعرضها وتعديلها !!
الاجابة: يتم تخزين النصوص داخل ال QTextDocument !!
اي كائن من النوع QTextEdit يحمل بداخله كائن من النوع QTextDocument والذي يستخدم لحفظ النصوص المنسقة والغير منسقة.
ويمكن استخدام QTextDocument مع اي كائن عرض اخر مثل QTextBrowser.
اذا باختصار :
QTextEdit has-a QTextDocument
ما هو ال QTextDocument ::
هو عبارة عن حاوية container للنصوص ، تدعم العديد من العناصر منها :
النصوص المنسقة ، القوائم، الجداول ، الاطارات والصور.
يتم الوصول الى محتويات هذا ال document برمجيا عن طريق مؤشر الكتابة QTextCursor.
اي يجب ان نستخدم الفئة QTextCursor لكي نستطيع ان نضيف اي شيء على ال document
*****************************
تركيبة ال rich text document ::
كما ذكرنا سابقا ، ان اي كائن QTextEdit يحوي كائن QTextDocument.
تعالوا نرى سويا تركيبة هذا المستند document ، وما هي العناصر التي يتعامل معها ::
يتكون هذا المستند document عند انشائه من اطار رئيسي يسمى ال rootFrame.
هذا الاطار سوف يحوي كل الكائنات الاخرى التي سنقوم بانشائها "جداول،اطارات،صور،كائنات اخر"
بشكل عام :
* اي document خالي يتكون من rootFrame وهذا الفريم يتكون من text block واحدة .
والمقصود ب text block اي وجود سطر خالي.
* اي document غير خالي ، فانه سيحوي rootFrame والذي بدوره سيحوي الكائنات التي سننشئها "اطارات،جداول،نصوص،فقرات..الخ".
*دائما يتم الفصل بين الجداول الاطارات بسطر خالي text block وذلك حتى نتمكن من ادخال عناصر بينهم.
كيفية الحصول على ال document ::
يمكن الحصول علي document من ال text edit كالاتي ::
كيفية الحصول على rootFrame ::
عناصر ال document :
يتكون من فقرات QTextBlock ، قوائم QTextList ، جداول QTextTable ، اطارات QTextFrame
و صور QTextImage
تلخيص ::
-ذكرنا سابقا ان كائن ال QTextEdit يحوي كائن من النوع QTextDocument
"اي ان ال text edit يحوي document"
- لادخال اي عنصر نريده داخل ال document لابد من التعامل مع ال QTextCursor
- ال document يتكون من اطار رئيسي والذي يتكون بدروه من فقره واحدة فقط text block
ما هو ال QTextCursor ::
بشكل مبسط هي عبارة عن فئة تمثل مؤشر كتابة ،تحوي معلومات عن موضعها position ، وتوفر دوال لادخال النصوص،الصور،الجداول،القوائم..الخ. الى ال document.
والهدف الرئيسي من استخدام ال cursor هو لادخال العناصر داخل ال document.
الحصول على ال cursor :
يمكن الحصول عليه من ال text edit كالاتي:
وهي الطريقة التي سأتبعها ،،
او من ال document مباشرة كالاتي :
****************************
ادخال نص :
لادخال نص نستخدم الدالة QTextCursor::insertText() كالاتي ::
وهذا مثال صغير ،، يوضح كيفية ادخال عدة نصوص ، مع التغيير في خصائص الخط:
الشرح ::
هنا قمنا بعمل مربع كتابة ، ثم قمنا بأخذ مؤشر الكتابة منه ، والذي سيكون حاليا في اعلى مربع الكتابة textEdit
ثم تم انشاء 4 متغيرات من النوع QTextCharFormat مع ضبط بعض الخصائص .
اخيرا تم استخدام الدالة QTextCursor::insertText() لادخال عدة نصوص مع الخصائص المناسبة.
******************************
ادخال فقرة جديدة :
وهذا يتم باستخدام الدالة QTextCursor.insertBlock() والتي تقوم بانهاء السطر الحالي
والانتقال الى سطر جديد.
مثال توضيحي :
****************************
ادخال اطار :
كما ذكرنا في بداية الدرس ،، انه اي document يحوي اطار يسمى rootFrame
هذا الاطار يحوي كل الكائنات الاخرى ، وهو يمثل الاطار الاب لجميع الاطارات التي سوف نقوم بانشائها.
دوال اساسية للتعامل مع الاطارات:
QTextDocument::rootFrame():تعود هذه الدالة بالاطار الرئيسي
QTextCursor::currentFrame(): تعود بالاطار الحالي "الاطار الذي يحوي مؤشر الكتابة"
QTextCursor::insertFrame(): تستخدم لادخال اطار جديد ، وترجع بمؤشر له.
QTextFrame::lastCursorPosition():تعود هذه الدالة باخر موضع في الاطار.
طبعا التعامل مع الاطارات يختلف قليلا عما سبق ، وذلك لانه بعد انشاء اطار فان مؤشر الكتابة سيكون داخل الاطار .
وهذا شيء جيد اذا اردنا الكتابة داخله ، ولكن ماذا عن كيفية الكتابة بعد الاطار اي خارجه!!
سنحتاج في هذه الحالة الى مؤشر الى الاطار الاب parent frame حتى نستطيع تحريك مؤشر الكتابة الى ما بعد الاطار الذي قمنا بانشائه.
مثال صغير لكي يوضح الفكرة ،،
الشرح ::
قمنا بانشاء مؤشر الى الاطار الاب "وفي هذه الحالة هو الاطار rootFrame" وذلك لاستخدامه فيما بعد لتحديد موقع مؤشر الكتابة.
اما هنا فقد قمنا باعداد بعض الخصائص للاطار الاب والابن، ثم قمنا بانشاء اطار يحوي بعض النصوص بداخله .
المشكلة تكمن الان في كيفية الكتابة خارج هذا الاطار !!
الحل باستخدام المؤشر الذي يشير الى الاطار الاب ، مع استخدام الدالة lastCursorPosition والتي تعني الانتقال الى اخر موضع.
**************************
ادخال جدول ::
ادخال الجدول يتم عن طريق الدالة QTextCursor::insertTable()
مع تمرير عدد الصفوف والاعمدة ، وكذلك خصائص الجدول عند الحاجة.
مثال توضيحي :
المثال يحوي العديد من التنسقيات والتي اعتقد انها واضحة جدا ،، لذلك سنركز على جزيئة ادخال الجدول :
هنا قمنا بانشاء جدول ،، لاحظ اننا قد قمنا بحفظه في مؤشر وذلك حتى نستطيع ادخال القيم اليه.
هذا السطر يعيد الينا الخلية من الصف i العمود j.
اما هنا فقد قمنا بوضع مؤشر الكتابة داخل اول خانة موجودة في الخلية .
وبعد ذلك قمنا بالكتابة بالشكل المعروف.
طبعا اذا اردنا ادخال عناصر على الجدول ،، فلازم نعمل تكرارين متداخلين nseted loop حتى نستطيع المرور على كل خلية.
*************************
ادخال القوائم ::
يتم عبر الدالة QTextCursor::insertList()
مثال يوضح كيفية عمل nested list :
الشرح ::
يتم ادخال القائمة عن طريق تحديد ال QTextListFormat اولا ،، وبعد ذلك يتم انشائها كالاتي::
***********************************************
ادخال صورة :
يتم الخطوات الاتية :
تحديد خصائص الصورة QTextImageFormt
ثم ادخالها عن طريق الدالة QTextCursor::insertImage()
وهذه محتويات ملف a.qrc :
*******************************
تحديد نص ::
لتحديد اي نص يجب ان نستخدم الدالة QTextCursor::movePosition()
وذلك تحريك مؤشر الكتابة من منطقة لاخرى ،، شوف المقطع الاتي ::
النتيجة : تحديد الكلمة التي يقع المؤشر بداخلها.
********************************
البحث عن نص::
َيتم ذلك من خلال الدالة QTextDocument::find()
والتي سترجع بمؤشر كتابة الي الكلمة التي بحثنا عنها او سترجع ب NULL اذا لم تتوفر الكلمة.
**********************************
طباعة ال document ::
يتم من خلال الدالة QTextDocument::print()
مقطع توضيحي :
*****************************
قراءة ملفات HTML :
سنقوم هنا بقراءة اي ملف يحوي كود HTML، وسنرى انه سيتم تنفيذ هذا الكود داخل ال text edit
مثال توضيحي ::
windget.h
widget.cpp
main.cpp
الى هنا نصل الى نهاية درس اليوم ،،
وتبقي فقط المشاريع ،، والتي سأبدأ منها ب Reports Builder هذه الايام ان شاء الله ،،
وسأدرجها عندما انتهي منها ،،
اي سؤال ؟؟ تعديل ؟؟ اقتراح ؟؟
...
الى اللقاء ،،
حديثنا اليوم سيكون عن كيفية معالجة النصوص داخل مربع النص QTextEdit
اي باختصار كيف نقوم بكتابة نصوص منسقة rich text داخل هذا المربع !!
محتويات الدرس :
- ما هو ال QTextEdit
- ما هو ال QTextDocument
- كيفية ادخال النصوص داخل ال QTextEdit
- ما هو المؤشر Cursor
- كيفية ادخال الجداول tables والاطارات frames والصور images
مشاريع تطبيقية :
- كتابة برنامج محرر نصوص Word Processor
- كتابة فئات لانشاء التقارير او برنامج Reports Builder
الموضوع بشكل كامل يتمحور حول ال QTextEdit,QTextDocument,QTextCursor
لذلك سوف نتناولهم اولا ثم ننتقل الى محتويات درس اليوم

* ملاحظة : جميع الاكواد في هذا الدرس هي اكواد توضيحية Toys Example، يعني ليست مكتوبة بطريقة عملية، والهدف هو لتوضيح الفكرة فقط بأقل عدد من الاسطر.
نبدأ على بركة الله مع QTextEdit ،،
************************
ما هو ال QTextEdit ::
هو عبارة عن اداة widget تستخدم لعرض وتعديل النصوص المنسقة rich text والغير منسقة plain text
ال plain text هي عبارة عن نصوص لا يحوي اي تنسيق مثل الاكواد التي نقوم بكتابتها في اي محرر.
اما ال rich text فهو عبارة عن نصوص منسقة اي تحوي الوان وجداول واطارات وخلفيات و...الخ.
استخدام ال QTextEdit ::
سنبدأ بمثال صغير ، وسنقوم بالتطبيق عليه.
كود:
#include <QApplication> #include <QTextEdit> int main(int argc,char* argv[]) { QApplication app(argc,argv); QTextEdit* textEdit=new QTextEdit; textEdit->show(); return app.exec(); }
كالعادة يجب ان نعلن اولا عن ملفات الرأس المستخدمة ،، لذلك لا تنسى تضمين الملف :
كود:
#include <QTextEdit>
كود:
QTextEdit* textEdit=new QTextEdit; textEdit->show();
الان قم بالكتابة علي text edit عدة اسطر ،، ولاحظ انه يقوم بانشاء ال scroll bar العمودي عندما تصل الى نهاية المربع.
تجربة بعض الخصائص والدوال ::
يوجد العديد من الخصائص والدوال المهمة لل QTextEdit ،، سنستعرض بعضا منها ::
خاصية لف السطر: اي الانتقال الى السطر الجديد .
الوضع الافتراضي هو WidgetWidth اي ان نهاية السطر تكون على حجم المربع.
يمكنك وضع خاصية لف السطر "الذهاب الى سطر جديد" تكون فقط عند الضغط على انتر كالاتي ::
كود:
textEdit->setLineWrapMode(QTextEdit::NoWrap);
كود:
textEdit->setLineWrapMode(QTextEdit::FixedPixelWidth); textEdit->setLineWrapColumnOrWidth(50);
كود:
textEdit->setLineWrapMode(QTextEdit::FixedColumnWidth); textEdit->setLineWrapColumnOrWidth(10);
الدوال الاكثر استخداما :
append():اضافة نص الى نهاية ال text edit
clear(): حذف كل النص في ال text edit
copy(): نسخ النص المحدد الى ال clipboard
cut(): قص النص المحدد.
paste(): لصق .
undo():الغاء اخر عملية.
redo(): اعادة اخر عملية.
selectAll(): نسخ الكل.
zoomIn(): تكبير النص
zoomOut(): تصغير النص
setAlignment(): وضع المحاذاة.
setFontWeight(): تحديد كثافة الخط
setFontUnderLine():وضع خط تحت النص
setFontPointSize():تحديد حجم النقطة
setCurrentFont():تحديد نوع الخط
setTextColor(): تحديد لون الخط.
setText(): وضع نص.
setPlainText():وضع نص غير منسق
setHtml(): وضع نص HTML
بعض ال SIGNAL ::
copyAvailable(): ترسل "emit" اذا كان هناك قابلية لعمل نسخ.
redoAvailable(): ايضا يتم استدعائها لكن اذا كان هناك قابلية لاعادة اخر عملية.
undoAvailable(): يتم استدعائها اذا كان هناك قابلية للتراجع
textChanged(): ترسل emit اذا حدث اي تغيير في محتويات ال QTextEdit.
اعتقد ان هذه الدوال كافية لعمل محرر نصوص بسيط جدا ،، بحيث لا يحوي جداول ولا صور ولا ..الخ.
راجع ال decumentation لمعرفة جميع الدوال وكذلك ال signals و ال slots.
**********************************
الان نعود مرة اخرى لتعريف ال QTextEdit والتي قلنا انها تستخدم لعرض وتعديل النصوص المنسقة والغير منسقة .
طيب السؤال المطروح الان : اين يتم تخزين النصوص اذا كان ال QTextEdit يستخدم لعرضها وتعديلها !!
الاجابة: يتم تخزين النصوص داخل ال QTextDocument !!
اي كائن من النوع QTextEdit يحمل بداخله كائن من النوع QTextDocument والذي يستخدم لحفظ النصوص المنسقة والغير منسقة.
ويمكن استخدام QTextDocument مع اي كائن عرض اخر مثل QTextBrowser.
اذا باختصار :
QTextEdit has-a QTextDocument
ما هو ال QTextDocument ::
هو عبارة عن حاوية container للنصوص ، تدعم العديد من العناصر منها :
النصوص المنسقة ، القوائم، الجداول ، الاطارات والصور.
يتم الوصول الى محتويات هذا ال document برمجيا عن طريق مؤشر الكتابة QTextCursor.
اي يجب ان نستخدم الفئة QTextCursor لكي نستطيع ان نضيف اي شيء على ال document
*****************************
تركيبة ال rich text document ::
كما ذكرنا سابقا ، ان اي كائن QTextEdit يحوي كائن QTextDocument.
تعالوا نرى سويا تركيبة هذا المستند document ، وما هي العناصر التي يتعامل معها ::
يتكون هذا المستند document عند انشائه من اطار رئيسي يسمى ال rootFrame.
هذا الاطار سوف يحوي كل الكائنات الاخرى التي سنقوم بانشائها "جداول،اطارات،صور،كائنات اخر"
بشكل عام :
* اي document خالي يتكون من rootFrame وهذا الفريم يتكون من text block واحدة .
والمقصود ب text block اي وجود سطر خالي.
* اي document غير خالي ، فانه سيحوي rootFrame والذي بدوره سيحوي الكائنات التي سننشئها "اطارات،جداول،نصوص،فقرات..الخ".
*دائما يتم الفصل بين الجداول الاطارات بسطر خالي text block وذلك حتى نتمكن من ادخال عناصر بينهم.
كيفية الحصول على ال document ::
يمكن الحصول علي document من ال text edit كالاتي ::
كود:
QTextDocument* document=textEdit->document();
كيفية الحصول على rootFrame ::
كود:
QTextFrame* root=document->rootFrame();
عناصر ال document :
يتكون من فقرات QTextBlock ، قوائم QTextList ، جداول QTextTable ، اطارات QTextFrame
و صور QTextImage
تلخيص ::
-ذكرنا سابقا ان كائن ال QTextEdit يحوي كائن من النوع QTextDocument
"اي ان ال text edit يحوي document"
- لادخال اي عنصر نريده داخل ال document لابد من التعامل مع ال QTextCursor
- ال document يتكون من اطار رئيسي والذي يتكون بدروه من فقره واحدة فقط text block
ما هو ال QTextCursor ::
بشكل مبسط هي عبارة عن فئة تمثل مؤشر كتابة ،تحوي معلومات عن موضعها position ، وتوفر دوال لادخال النصوص،الصور،الجداول،القوائم..الخ. الى ال document.
والهدف الرئيسي من استخدام ال cursor هو لادخال العناصر داخل ال document.
الحصول على ال cursor :
يمكن الحصول عليه من ال text edit كالاتي:
كود:
QTextEdit* textEdit=new QTextEdit; QTextCursor cursor=textEdit->textCursor();
او من ال document مباشرة كالاتي :
كود:
QTextDocument* document=new QTextDocument(textEdit); QTextCursor cursor(document);
****************************
ادخال نص :
لادخال نص نستخدم الدالة QTextCursor::insertText() كالاتي ::
كود:
cursor.insertText("Ahmad Essam");
كود:
#include <QApplication> #include <QTextEdit> #include <QTextCharFormat> int main(int argc,char* argv[]) { QApplication app(argc,argv); QTextEdit* textEdit=new QTextEdit; QTextCursor cursor=textEdit->textCursor(); QTextCharFormat boldFormat; QTextCharFormat italicFormat; QTextCharFormat defaultFormat; QTextCharFormat customFormat; boldFormat.setFontWeight(QFont::Bold); italicFormat.setFontItalic(true); customFormat.setForeground(QColor(Qt::red)); customFormat.setFont(QFont("Arial",14,QFont::Bold)); customFormat.setFontUnderline(true); cursor.insertText("Personal Info.",customFormat); cursor.insertBlock(); cursor.insertBlock(); cursor.insertText("Ahmad Essam",defaultFormat); cursor.insertBlock(); cursor.insertText("Faculty of Mathematical Sciences",boldFormat); cursor.insertBlock(); cursor.insertText("Computer Science Dept.",boldFormat); cursor.insertBlock(); cursor.insertBlock(); cursor.insertText("ByE",italicFormat); cursor.insertBlock(); textEdit->show(); return app.exec(); }
الشرح ::
كود:
QTextEdit* textEdit=new QTextEdit; QTextCursor cursor=textEdit->textCursor();
كود:
QTextCharFormat boldFormat; QTextCharFormat italicFormat; QTextCharFormat defaultFormat; QTextCharFormat customFormat; boldFormat.setFontWeight(QFont::Bold); italicFormat.setFontItalic(true); customFormat.setForeground(QColor(Qt::red)); customFormat.setFont(QFont("Arial",14,QFont::Bold)); customFormat.setFontUnderline(true);
كود:
cursor.insertText("Personal Info.",customFormat);
******************************
ادخال فقرة جديدة :
وهذا يتم باستخدام الدالة QTextCursor.insertBlock() والتي تقوم بانهاء السطر الحالي
والانتقال الى سطر جديد.
مثال توضيحي :
كود:
#include <QApplication> #include <QTextEdit> #include <QTextCharFormat> int main(int argc,char* argv[]) { QApplication app(argc,argv); QTextEdit* textEdit=new QTextEdit; QTextCursor cursor=textEdit->textCursor(); QTextBlockFormat colorFormat; QTextBlockFormat defaultFormat; QTextBlockFormat alignFormat; colorFormat.setBackground(QColor(Qt::gray)); alignFormat.setAlignment(Qt::AlignHCenter); cursor.setBlockFormat(colorFormat); cursor.insertText("Personal Info."); cursor.insertBlock(); cursor.insertText("Ahmad Essam"); cursor.setBlockFormat(alignFormat); cursor.insertBlock(); cursor.insertText("Faculty of Mathematical Sciences"); cursor.insertBlock(); cursor.insertText("Computer Science Dept."); cursor.insertBlock(); cursor.setBlockFormat(defaultFormat); cursor.insertBlock(); cursor.insertText("Bye."); textEdit->show(); return app.exec(); }
****************************
ادخال اطار :
كما ذكرنا في بداية الدرس ،، انه اي document يحوي اطار يسمى rootFrame
هذا الاطار يحوي كل الكائنات الاخرى ، وهو يمثل الاطار الاب لجميع الاطارات التي سوف نقوم بانشائها.
دوال اساسية للتعامل مع الاطارات:
QTextDocument::rootFrame():تعود هذه الدالة بالاطار الرئيسي
QTextCursor::currentFrame(): تعود بالاطار الحالي "الاطار الذي يحوي مؤشر الكتابة"
QTextCursor::insertFrame(): تستخدم لادخال اطار جديد ، وترجع بمؤشر له.
QTextFrame::lastCursorPosition():تعود هذه الدالة باخر موضع في الاطار.
طبعا التعامل مع الاطارات يختلف قليلا عما سبق ، وذلك لانه بعد انشاء اطار فان مؤشر الكتابة سيكون داخل الاطار .
وهذا شيء جيد اذا اردنا الكتابة داخله ، ولكن ماذا عن كيفية الكتابة بعد الاطار اي خارجه!!
سنحتاج في هذه الحالة الى مؤشر الى الاطار الاب parent frame حتى نستطيع تحريك مؤشر الكتابة الى ما بعد الاطار الذي قمنا بانشائه.
مثال صغير لكي يوضح الفكرة ،،
كود:
#include <QApplication> #include <QTextEdit> #include <QTextFrame> int main(int argc,char* argv[]) { QApplication app(argc,argv); QTextEdit* textEdit=new QTextEdit; QTextCursor cursor=textEdit->textCursor(); QTextFrame* root=cursor.currentFrame(); //or use QTextFrame* root=textEdit->document()->rootFrame(); QTextFrameFormat mainFrameFormat; QTextFrameFormat childFrameFormat; mainFrameFormat.setPadding(8); childFrameFormat.setPadding(8); childFrameFormat.setBorder(2); childFrameFormat.setPosition(QTextFrameFormat::FloatRight); childFrameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Ridge); childFrameFormat.setBorderBrush(QColor(Qt::darkGreen)); root->setFrameFormat(mainFrameFormat); cursor.insertText("This is the first text in the root frame"); cursor.insertBlock(); cursor.insertFrame(childFrameFormat); cursor.insertText("This is the second text in the child frame"); cursor.insertBlock(); cursor.insertText("im also in the child frame"); cursor.insertBlock(); cursor.insertText("how can i go out from this frame??"); cursor=root->lastCursorPosition(); cursor.insertText("i'm out of child frame"); cursor.insertBlock(); cursor.insertText("Good Bye"); textEdit->show(); return app.exec(); }
الشرح ::
كود:
QTextFrame* root=cursor.currentFrame();
كود:
QTextFrameFormat mainFrameFormat; QTextFrameFormat childFrameFormat; mainFrameFormat.setPadding(8); childFrameFormat.setPadding(8); childFrameFormat.setBorder(2); childFrameFormat.setPosition(QTextFrameFormat::FloatRight); childFrameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Ridge); childFrameFormat.setBorderBrush(QColor(Qt::darkGreen)); root->setFrameFormat(mainFrameFormat); cursor.insertFrame(childFrameFormat); cursor.insertText("This is the second text in the child frame"); cursor.insertBlock(); cursor.insertText("im also in the child frame"); cursor.insertBlock(); cursor.insertText("how can i go out from this frame??");
المشكلة تكمن الان في كيفية الكتابة خارج هذا الاطار !!
كود:
cursor=root->lastCursorPosition();
**************************
ادخال جدول ::
ادخال الجدول يتم عن طريق الدالة QTextCursor::insertTable()
مع تمرير عدد الصفوف والاعمدة ، وكذلك خصائص الجدول عند الحاجة.
مثال توضيحي :
كود:
#include <QApplication> #include <QTextEdit> #include <QTextTableCell> const int ROW=5; const int COL=4; int main(int argc,char* argv[]) { QApplication app(argc,argv); QStringList list; list<<"ID"<<"First Name"<<"Last Name"<<"Phone Number"; QTextCharFormat cellFormat; cellFormat.setBackground(QColor(Qt::lightGray)); QVector<QTextLength> constraints; constraints<<QTextLength(QTextLength::PercentageLength,25); constraints<<QTextLength(QTextLength::PercentageLength,25); constraints<<QTextLength(QTextLength::PercentageLength,25); constraints<<QTextLength(QTextLength::PercentageLength,25); QTextEdit* textEdit=new QTextEdit; textEdit->setReadOnly(true); QTextCursor cursor=textEdit->textCursor(); QTextCharFormat boldFormat; QTextCharFormat defaultFormat; boldFormat.setFontWeight(QFont::Bold); QTextTableFormat tableFormat; tableFormat.setBackground(QColor(Qt::gray)); tableFormat.setAlignment(Qt::AlignHCenter); tableFormat.setColumnWidthConstraints(constraints); tableFormat.setCellPadding(3); cursor.insertText("this Eample demonstrates how to construct a table"); QTextTable* table=cursor.insertTable(ROW,COL,tableFormat); for(int j=0;j<COL;j++) { QTextTableCell cell=table->cellAt(0,j); cell.setFormat(cellFormat); cursor=cell.firstCursorPosition(); cursor.insertText(list[j],boldFormat); } cursor=textEdit->document()->rootFrame()->lastCursorPosition(); cursor.insertText("this line is outside of the table",defaultFormat); cursor.insertBlock(); cursor.insertText("and this text edit is "); cursor.insertText("Read-Only",boldFormat); textEdit->show(); return app.exec(); }
المثال يحوي العديد من التنسقيات والتي اعتقد انها واضحة جدا ،، لذلك سنركز على جزيئة ادخال الجدول :
كود:
QTextTable* table=cursor.insertTable(ROW,COL,tableFormat);
كود:
QTextTableCell cell=table->cellAt(i,j);
كود:
cursor=cell.firstCursorPosition();
وبعد ذلك قمنا بالكتابة بالشكل المعروف.
طبعا اذا اردنا ادخال عناصر على الجدول ،، فلازم نعمل تكرارين متداخلين nseted loop حتى نستطيع المرور على كل خلية.
*************************
ادخال القوائم ::
يتم عبر الدالة QTextCursor::insertList()
مثال يوضح كيفية عمل nested list :
كود:
#include <QApplication> #include <QTextEdit> int main(int argc,char* argv[]) { QApplication app(argc,argv); QTextEdit* textEdit=new QTextEdit; QTextCursor cursor=textEdit->textCursor(); cursor.insertText("Qt's feature:"); QTextListFormat listFormat; listFormat.setStyle(QTextListFormat::ListDisc); listFormat.setIndent(1); cursor.insertList(listFormat); cursor.insertText("Esay to use"); cursor.insertBlock(); cursor.insertText("Esay to learn"); cursor.insertBlock(); cursor.insertText("and importantly, Open Source "); cursor.insertBlock(); cursor.insertText("support a lot of thing:"); listFormat.setIndent(listFormat.indent()+1); cursor.insertList(listFormat); cursor.insertText("Database connectivity"); cursor.insertBlock(); cursor.insertText("Network API"); cursor.insertBlock(); cursor.insertText("XML support"); cursor.insertBlock(); cursor.insertText("OpenGL,Multithreading and more."); textEdit->show(); return app.exec(); }
يتم ادخال القائمة عن طريق تحديد ال QTextListFormat اولا ،، وبعد ذلك يتم انشائها كالاتي::
كود:
cursor.insertList(listFormat);
***********************************************
ادخال صورة :
يتم الخطوات الاتية :
تحديد خصائص الصورة QTextImageFormt
ثم ادخالها عن طريق الدالة QTextCursor::insertImage()
كود:
#include <QApplication> #include <QTextEdit> #include <QTextFrame> int main(int argc,char* argv[]) { Q_INIT_RESOURCE(a); QApplication app(argc,argv); QTextEdit* textEdit=new QTextEdit; QTextCursor cursor=textEdit->textCursor(); QTextImageFormat imageFormat; imageFormat.setName(":/images/a.png"); cursor.insertImage(imageFormat); QTextCharFormat customFormat; customFormat.setFont(QFont("Arial",13,QFont::Bold)); customFormat.setForeground(QColor(Qt::red)); cursor.insertBlock(); cursor.insertBlock(); cursor.insertText("Live Free or Die",customFormat); textEdit->show(); return app.exec(); }
وهذه محتويات ملف a.qrc :
كود:
<!DOCTYPE RCC><RCC version="1.0"> <qresource> <file>images/a.png</file> </qresource> </RCC>
*******************************
تحديد نص ::
لتحديد اي نص يجب ان نستخدم الدالة QTextCursor::movePosition()
وذلك تحريك مؤشر الكتابة من منطقة لاخرى ،، شوف المقطع الاتي ::
كود:
cursor.movePosition(QTextCursor::StartOfWord); cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
********************************
البحث عن نص::
َيتم ذلك من خلال الدالة QTextDocument::find()
والتي سترجع بمؤشر كتابة الي الكلمة التي بحثنا عنها او سترجع ب NULL اذا لم تتوفر الكلمة.
**********************************
طباعة ال document ::
يتم من خلال الدالة QTextDocument::print()
مقطع توضيحي :
كود:
QTextDocument *document = editor->document(); QPrinter printer; QPrintDialog *dlg = new QPrintDialog(&printer, this); if (dlg->exec() != QDialog::Accepted) return; document->print(&printer);
*****************************
قراءة ملفات HTML :
سنقوم هنا بقراءة اي ملف يحوي كود HTML، وسنرى انه سيتم تنفيذ هذا الكود داخل ال text edit
مثال توضيحي ::
windget.h
كود:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> class QTextEdit; class Widget:public QWidget { Q_OBJECT public: Widget(QWidget* parent=0); public slots: void readClicked(); void clearClicked(); private: QTextEdit* textEdit; void loadFile(const QString& file); }; #endif
widget.cpp
كود:
#include <QtGui> #include "widget.h" Widget::Widget(QWidget* parent): QWidget(parent) { textEdit=new QTextEdit; QPushButton* readButton=new QPushButton("Read"); QPushButton* quitButton=new QPushButton("Quit"); QPushButton* clearButton=new QPushButton("Clear"); connect(readButton,SIGNAL(clicked()),this,SLOT(readClicked())); connect(quitButton,SIGNAL(clicked()),this,SLOT(close())); connect(clearButton,SIGNAL(clicked()),this,SLOT(clearClicked())); QHBoxLayout* hLayout=new QHBoxLayout; hLayout->addWidget(readButton); hLayout->addWidget(quitButton); hLayout->addWidget(clearButton); QVBoxLayout* layout=new QVBoxLayout; layout->addLayout(hLayout); layout->addWidget(textEdit); setLayout(layout); setWindowTitle("text editor with capability of export/import HTML files"); } void Widget::clearClicked() { textEdit->clear(); } void Widget::readClicked() { QString file=QFileDialog::getOpenFileName(this); if(!file.isEmpty()) loadFile(file); } void Widget::loadFile(const QString& fileName) { QFile file(fileName); if( !file.open(QFile::ReadOnly|QFile::Text) ) { QMessageBox::warning(this,"Error",tr("Cannot read file %1:\n%2").arg(fileName).arg(file.errorString())); return ; } QTextStream in(&file); QApplication::setOverrideCursor(Qt::WaitCursor); textEdit->setHtml(in.readAll()); QApplication::restoreOverrideCursor(); }
main.cpp
كود:
#include <QApplication> #include "widget.h" int main(int argc,char* argv[]) { QApplication app(argc,argv); Widget widget; widget.show(); return app.exec(); }
الى هنا نصل الى نهاية درس اليوم ،،
وتبقي فقط المشاريع ،، والتي سأبدأ منها ب Reports Builder هذه الايام ان شاء الله ،،
وسأدرجها عندما انتهي منها ،،
اي سؤال ؟؟ تعديل ؟؟ اقتراح ؟؟
...
الى اللقاء ،،

تعليق