واجهة مستخدم ذات إطارات في برنامج Java. عملية تطوير برنامج واجهة المستخدم الرسومية البسيط في Java

08.07.2019

نموذج الشاشة عبارة عن منطقة تظهر على الشاشة على شكل نافذة تحتوي على عناصر مختلفة - الأزرار والنصوص والقوائم المنسدلة وما إلى ذلك. وهذه العناصر نفسها تسمى المكونات.

تسمى البيئات التي تسمح لك بوضع المكونات بشكل تفاعلي في النماذج وتعيين معلماتها أثناء تطوير التطبيق ببيئات RAD. يرمز RAD إلى التطوير السريع للتطبيقات - التطوير السريع للتطبيقات.

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

NetBeans عبارة عن بيئة RAD تتيح لك إنشاء تطبيقات بسرعة وسهولة باستخدام واجهة مستخدم رسومية غنية (GUI). على الرغم من أن بنيات لغة Java التي تتيح لك القيام بذلك ليست بسيطة للغاية، إلا أنه في المرحلة الأولية من العمل مع نماذج الشاشة وعناصرها ليست هناك حاجة للخوض في هذه التفاصيل الدقيقة. يكفي معرفة المبادئ الأساسية للعمل مع مثل هذه المشاريع.

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

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

مثال على فتح مشروع باستخدام كود المصدر الموجود.

يحتوي NetBeans 5.0 على مثال جيد لتطبيق واجهة المستخدم الرسومية، لكن NetBeans 5.5 لا يحتوي على واحد. لذلك، لمزيد من العمل، يجب عليك نسخ مثال مماثل من موقع المؤلف أو الموقع الذي تم نشر هذه الدورة التدريبية عليه. يُسمى المثال JavaApplicationGUI_example.

أولاً، يجب عليك فك ضغط الأرشيف المضغوط واستخراج المجلد الذي يحتوي على ملفات المشروع الموجودة فيه إلى المجلد الذي يحتوي على مشاريعك (على سبيل المثال، C:\Documents وSettings\User). ثم ابدأ تشغيل بيئة NetBeans إذا لم تكن قيد التشغيل بالفعل وأغلق أي مشروعات مفتوحة لإبعادها عن الطريق. ثم حدد File/Open Project من القائمة، أو الأيقونة التي تحتوي على مجلد أرجواني مفتوح على شريط الأدوات، أو اضغط على مجموعة المفاتيح ++يا. في مربع الحوار الذي يفتح، حدد مجلدًا JavaApplicationGUI_example(من الأفضل عدم الخوض فيه، ولكن فقط قم بتعيين التحديد لهذا المجلد)، ثم انقر فوق الزر "فتح مجلد المشروع".

في هذه الحالة، إذا لم تقم بإلغاء تحديد خانة الاختيار "فتح كمشروع رئيسي"، يصبح المشروع هو المشروع الرئيسي تلقائيًا.

يظهر النص التالي في نافذة محرر التعليمات البرمجية المصدر:

* GUI_application.java

الحزمة java_gui_example؛

* @ المؤلف فاديم موناخوف

يمتد تطبيق GUI_application للفئة العامة javax.swing.JFrame (

* إنشاء نموذج جديد GUI_application

تطبيق GUI_application() العام (

initComponents();

/** يتم استدعاء هذه الطريقة من داخل المنشئ إلى

* تهيئة النموذج.

* تحذير: لا تقم بتعديل هذا الرمز. محتوى هذه الطريقة هو

* يتم تجديده دائمًا بواسطة محرر النماذج.

خروج الفراغ الخاصMenuItemActionPerformed(java.awt.event.ActionEvent evt)

*param وسيطة وسيطات سطر الأوامر

الفراغ العام الثابت الرئيسي (وسائط السلسلة) (

java.awt.EventQueue.invocLater(new Runnable() (

تشغيل الفراغ العام () (

new GUI_application().setVisible(true);

// إعلان المتغيرات - لا تقم بتعديله

javax.swing.JMenuItem الخاص aboutMenuItem؛

javax.swing.JMenuItem contentMenuItem;

javax.swing.JMenuItem الخاص CopyMenuItem؛

خاص javax.swing.JMenuItem CutMenuItem؛

Private javax.swing.JMenuItemdeleteMenuItem;

javax.swing.JMenu الخاص تحرير القائمة؛

javax.swing.JMenuItem الخاص خروجMenuItem؛

javax.swing.JMenu الخاص fileMenu؛

javax.swing.JMenu الخاص helpMenu؛

خاص javax.swing.JMenuBar MenuBar؛

javax.swing.JMenuItem الخاص openMenuItem؛

خاص javax.swing.JMenuItem لصقMenuItem؛

javax.swing.JMenuItem الخاص saveAsMenuItem؛

javax.swing.JMenuItem الخاص saveMenuItem؛

// نهاية إعلان المتغيرات

دعونا نشرح بعض أجزائه. نحن على دراية بالفعل بتحديد الحزمة java_gui_example التي سيتم وضع رمز فئة التطبيق فيها. يعد الإعلان عن فئة GUI_application نفسها في هذه الحالة أكثر تعقيدًا إلى حد ما من ذي قبل:

يمتد تطبيق GUI_application للفئة العامة إلى javax.swing.JFrame

هذا يعني أنه تم تعريف الفئة العامة GUI_application، وهي سليل فئة JFrame المحددة في الحزمة المتأرجحة، والمتداخلة في حزمة javax. تتم ترجمة الكلمة "يمتد" على أنها "تمتد" (الطبقة السليلة تعمل دائمًا على توسيع قدرات فئة السلف).

يقوم منشئ GUI_application() العام بإنشاء كائن تطبيق وتهيئة جميع مكوناته باستخدام طريقة initComponents()، والتي يتم إنشاؤها تلقائيًا بواسطة بيئة التطوير وإخفائها في التعليمات البرمجية المصدر بواسطة عقدة +Generated Code.

من خلال توسيع العقدة، يمكنك رؤية تنفيذ هذه الطريقة، ولكن لا يمكنك تغيير التعليمات البرمجية. لن نتطرق إلى ما يحدث فيه.

خروج الفراغ الخاصMenuItemActionPerformed

سيتم مناقشتها في وقت لاحق قليلا. طريقة

الفراغ العام الثابت الرئيسي (وسائط السلسلة)

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

تشغيل التطبيق. تطبيق مع قائمة موسعة.

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

يكون عامل ExitMenuItemActionPerformed مسؤولاً عن النقر فوق عنصر القائمة هذا. عند تصميم نموذج الشاشة، يتم تعيينه كـ معالج الحدث– روتين فرعي يتم تنفيذه عند وقوع حدث ما. في حالتنا، الحدث هو اختيار عنصر القائمة "إنهاء"، ويتم استدعاء معالج ExitMenuItemActionPerformed. يوجد خط واحد فقط بداخله

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

محرر الشاشة

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

تحرير نموذج الشاشة.

بدلاً من الكود المصدري، يتم عرض مظهر نموذج الشاشة والمكونات الموجودة عليه. على يمين النافذة التي يتم فيها عرض نموذج الشاشة في وضع التحرير، توجد نوافذ اللوحة الخاصة بلوحة المكونات ونافذة الخصائص لعرض وتحرير خصائص المكون الحالي.

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

تم تصميم لوحة المكونات لتحديد نوع المكون الذي يحتاج المبرمج إلى وضعه على نموذج الشاشة. على سبيل المثال، دعونا نضيف مكونًا من نوع JButton إلى النموذج الخاص بنا (اختصار لـ Java Button - "Java Button"). للقيام بذلك، انقر فوق عنصر JButton الموجود على اللوحة وحرك الماوس إلى الموقع المطلوب على نموذج الشاشة. عندما يضرب الماوس منطقة من نموذج الشاشة، يظهر عليها زر ذو حجم قياسي، يتحرك بالماوس. يؤدي النقر فوق الموقع المطلوب في النموذج إلى بقاء الزر في ذلك الموقع. يظهر إطار ومربعات صغيرة حوله، مما يشير إلى أنه تم تحديد المكون الخاص بنا. يتم عرض الخصائص الخاصة به وتحريرها في نافذة الخصائص.

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

افتراضيًا، يتم تحديد تسميات المكونات كاسم النوع متبوعًا برقم المكون. ولكن بدلاً من الحرف الكبير، على عكس اسم النوع، يتم استخدام حرف صغير. لذلك، سيتم تسمية الزر الأول بـ jButton1، والثاني - jButton2، وما إلى ذلك. المتغيرات المقابلة للأزرار التي تم إنشاؤها تلقائيًا في الكود المصدري سيكون لها نفس الأسماء.

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

أدخل "موافق" على الزر - استخدم هذا الزر للخروج من البرنامج.

تحرير خصائص المكونات

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

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

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

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

يتم عرض الخصائص المنطقية في عمود قيمة الخاصية كأزرار تحديد خانة اختيار - مربعات مع إمكانية وضع علامة اختيار بالداخل. إذا لم تكن هناك علامة اختيار، فإن قيمة الخاصية تكون خاطئة؛ وإذا كانت موجودة، تكون قيمة الخاصية صحيحة.

باستخدام الزر كمثال، ندرج عددًا من أهم الخصائص التي يمكن تعيينها للمكونات. ينطبق الكثير منها على المكونات الأخرى أيضًا.

اسم الخاصية ماذا يطلب
خلفية لون الخلفية
ComponentPopupMenu يسمح لك بتعيين قائمة منبثقة تظهر عند النقر بزر الماوس الأيمن في منطقة المكون.
الخط الخط المستخدم للكتابة على المكون.
المقدمة لون الخط المستخدم للنقش على المكون.
أيقونة صورة يتم رسمها على المكون المجاور للنص.
نص النص (التسمية) على المكون.
نص تلميح الأداة تلميح أداة يظهر بعد فترة من الوقت عند تحريك الماوس فوق أحد المكونات.
حدود نوع الإطار المحيط بالمكون.
borderPainted ما إذا كان يتم رسم الحدود حول المكون.
contentAreaFilled هل هناك تعبئة لونية للمنطقة الداخلية للمكون (بالنسبة للأزرار، فإنها تخلق تأثيرًا ثلاثي الأبعاد؛ بدون التعبئة، يبدو الزر مسطحًا).
defaultCapable هل الزر قادر على أن يكون "زرًا افتراضيًا": عند الضغط عليه يتم الضغط على "الزر الافتراضي" تلقائيًا (يجب أن يكون هناك زر واحد في نموذج الشاشة).
ممكّن ما إذا كان المكون متاحًا. بشكل افتراضي، تتوفر كافة المكونات التي تم إنشاؤها في النموذج. يتم طلاء المكونات التي يتعذر الوصول إليها بألوان باهتة.

على سبيل المثال، دعونا نضيف تلميح أداة للزر الخاص بنا: أدخل النص "هذا الزر مخصص للخروج من البرنامج" في الحقل المقابل لخاصية ToolTipText. لسوء الحظ، يمكن أن يكون التلميح مكونًا من سطر واحد فقط - حيث يتم تجاهل أحرف السطر الجديد عند عرض التلميح، حتى لو تم تحديدها في السطر برمجيًا.

أخيرًا، لنقم بتعيين الإجراء الذي سيتم تنفيذه عند النقر فوق الزر - معالج الحدثنقرات زر (معالج الأحداث). للقيام بذلك، حدد الزر أولاً، ثم انقر بزر الماوس الأيمن عليه، وفي القائمة المنبثقة التي تظهر، حدد الأحداث/الإجراء/الإجراء.

تعيين معالج الأحداث

"الأحداث" تعني "الأحداث"، والإجراء يعني "الإجراء"، والإجراء الذي تم تنفيذه يعني "الإجراء الذي تم تنفيذه".

بعد ذلك، سيحدث انتقال تلقائي إلى محرر التعليمات البرمجية المصدر، وسيظهر معالج حدث القالب هناك:

// TODO أضف رمز المعالجة الخاص بك هنا:

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

بجوار المعالج jButton1ActionPerformed، سيكون هناك معالج حدث موجود يتم تشغيله عند النقر فوق عنصر القائمة "خروج":

خروج الفراغ الخاصMenuItemActionPerformed(java.awt.event.ActionEvent evt) (

لنستبدل السطر الذي يحتوي على التعليق في معالج الأحداث الخاص بنا بالكود الذي يتسبب في خروج البرنامج:

الفراغ الخاص jButton1ActionPerformed(java.awt.event.ActionEvent evt) (

الآن، بعد تشغيل تطبيقنا، سيؤدي تحريك مؤشر الماوس إلى الزر إلى ظهور تلميح أداة، وسيؤدي النقر فوق الزر إلى الخروج من البرنامج.

من الحالات الشائعة عرض رسالة عند وقوع حدث ما، على سبيل المثال، الضغط على زر. في هذه الحالة، يتم استدعاء اللوحة بالرسالة:

javax.swing.JOptionPane.showMessageDialog(null,"لقد تم النقر فوقي");

إذا تم استيراد فئات الحزمة javax.swing، فلن تكون هناك حاجة إلى بادئة javax.swing عند استدعائها.

مظهر التطبيق

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

ظهور تطبيق قيد التشغيل مع واجهة مستخدم مستقلة عن النظام الأساسي يتم تعيينها افتراضيًا

بالإضافة إلى ذلك، يظهر تطبيقنا في الزاوية اليسرى العليا من الشاشة، ولكننا نرغب في ظهوره في المنتصف.

من أجل إظهار التطبيق في نموذج خاص بالمنصة (أي في النموذج الذي يستخدم مكونات وإعدادات نظام التشغيل)، تحتاج إلى تغيير رمز مُنشئ التطبيق عن طريق إدخال نوع واجهة المستخدم (واجهة المستخدم، مختصرة UI) قبل استدعاء الأسلوب initComponents:

استيراد javax.swing.*;

import java.awt.*;

تطبيق GUI_application() العام (

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

)catch(استثناء e)();

initComponents();

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

حجم إطار البعد = getSize();

setLocation(نقطة جديدة((screenSize.width-frameSize.width)/2,

(screenSize.height-frameSize.width)/2)

ظهور تطبيق قيد التشغيل مع واجهة مستخدم موجهة نحو النظام الأساسي في نظام التشغيل Windows ® XP

الكود الذي يتبع استدعاء initComponents() هو ضبط نافذة التطبيق في منتصف الشاشة.

من الممكن تحديد نوع آخر من التطبيقات المستقلة عن النظام الأساسي - بأسلوب Motiff المستخدم في نظام التشغيل Solaris ®. لتعيين هذا النوع بدلا من الاتصال

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()

ينبغي أن تكون مكتوبة

UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");

ظهور تطبيق قيد التشغيل مع واجهة مستخدم مستقلة عن النظام الأساسي بأسلوب Motiff

ستصبح الإنشاءات المستخدمة واضحة للقارئ بعد دراسة الأقسام الإضافية من الدليل.

ادارة مشروع

لكي لا تخلط بين المشاريع المختلفة وإصداراتها، خاصة مع الأخذ في الاعتبار حقيقة أن المشاريع التعليمية غالبًا ما تحتاج إلى النقل من كمبيوتر إلى آخر، يجب أن تأخذ إدارة المشروع على محمل الجد. قام المؤلف، نتيجة لسنوات عديدة من الخبرة في العمل مع لغات وبيئات برمجة مختلفة، بتطوير النظام التالي (تم تصحيحه بالتطبيق على بيئة NetBeans):

· يتم إنشاء مجلد باسم المشروع لكل مشروع. سوف نسميه مجلد الأرشيف لهذا المشروع. يمكن أن تكون أسماء المجلدات المستخدمة باللغة الروسية، وكذلك أسماء التطبيقات والملفات.

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

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

· عندما تتلقى نسخة قابلة للتنفيذ إلى حد ما من المشروع، يجب عليك عمل نسخة أرشيفية منها. للقيام بذلك، في مشروع مفتوح في نافذة "المشاريع"، ما عليك سوى النقر بزر الماوس الأيمن على اسم المشروع وتحديد "نسخ المشروع" من القائمة المنبثقة التي تظهر. سيتم فتح نموذج حوار يتم فيه اقتراح اسم نسخة تم إنشاؤه تلقائيًا - تتم إضافة شرطة سفلية ورقم نسخة إلى اسم المشروع الأصلي. للنسخة الأولى هو _1، للنسخة الثانية _2، وهكذا. علاوة على ذلك، يظل المجلد الرئيسي للأرشيف بشكل افتراضي هو نفس مجلد المشروع الأصلي. وهو أمر مريح للغاية، لأنه يجعل من الممكن إنشاء نسخة بثلاث نقرات فقط بالماوس دون كتابة أي شيء من لوحة المفاتيح.

إنشاء نسخة عمل من المشروع

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

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

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

  • السياسة الخارجية لاتحاد الجمهوريات الاشتراكية السوفياتية خلال سنوات الحرب. الإقراض والتأجير. مؤتمر طهران. مؤتمرات يالطا وبوتسدام 1945 إنشاء الأمم المتحدة.
  • السياسة الخارجية لاتحاد الجمهوريات الاشتراكية السوفياتية خلال الحرب. مؤتمر طهران. مؤتمر يالطا وبوتسدام 1945 إنشاء الأمم المتحدة.
  • استئناف أنشطة BSG. إنشاء الأحزاب والمنظمات البلناطية

  • لقد مرت واجهة المستخدم في Java بمسار شائك للغاية من التكوين والتطوير. لفترة طويلة تم اتهامه بالبطء في العمل والجشع لموارد النظام والوظائف المحدودة. أدى ظهور .NET مع مكونات رسومية أسرع إلى تقويض مكانة Java. لكن كل سحابة لها جانب إيجابي - كل هذه الحركة حفزت مطوري Java على تطوير مكتبات الرسومات وتحسينها. دعونا نرى ما سيأتي منه.

    مجموعة أدوات النافذة المجردة

    كانت AWT هي محاولة Sun الأولى لإنشاء واجهة مستخدم رسومية لـ Java. لقد سلكوا الطريق السهل وقاموا ببساطة بإنشاء طبقة Java تستدعي الأساليب من المكتبات المكتوبة بلغة C. وتقوم أساليب المكتبة بإنشاء المكونات الرسومية لبيئة التشغيل واستخدامها. من ناحية، يعد هذا أمرًا جيدًا، نظرًا لأن برنامج Java يشبه البرامج الأخرى داخل نظام التشغيل هذا. ولكن من ناحية أخرى، ليس هناك ما يضمن أن الاختلافات في أحجام المكونات والخطوط لن تفسد مظهر البرنامج عند تشغيله على منصة أخرى. بالإضافة إلى ذلك، لضمان وظائف الأنظمة الأساسية المتعددة، كان من الضروري توحيد واجهات استدعاء المكونات، ولهذا السبب تم تقليل وظائفها قليلاً. وتبين أن مجموعة المكونات صغيرة جدًا. على سبيل المثال، لا يحتوي AWT على جداول، ولا تدعم الأزرار عرض الرموز.

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

    مزايا:

    • جزء JDK؛
    • سرعة العمل
    • المكونات الرسومية تشبه المكونات القياسية.

    عيوب:

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

    خاتمة:

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

    يتأرجح


    بعد AWT، طورت Sun مجموعة من مكونات الرسومات تسمى Swing. تمت كتابة مكونات التأرجح بالكامل بلغة Java. يتم استخدام تقنية 2D في العرض، وهو ما يجلب معه العديد من المزايا. تتجاوز مجموعة المكونات القياسية AWT بشكل كبير من حيث التنوع والوظائف. لقد أصبح من السهل إنشاء مكونات جديدة، وراثة المكونات الموجودة ورسم ما تشتهيه نفسك. أصبح دعم الأنماط والجلود المختلفة ممكنًا. ومع ذلك، فإن سرعة الإصدارات الأولى من Swing تركت الكثير مما هو مرغوب فيه. قد يؤدي البرنامج المكتوب بشكل غير صحيح إلى تعليق Windows بالكامل.

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

    مزايا:

    • جزء من JDK، لا حاجة لتثبيت مكتبات إضافية؛
    • هناك العديد من الكتب حول Swing والإجابات في المنتديات. جميع المشاكل، خاصة للمبتدئين، معروفة تمامًا لدى Google؛
    • محرر نماذج مدمج في جميع بيئات التطوير تقريبًا؛
    • هناك العديد من الامتدادات المبنية على التأرجح مثل SwingX؛
    • دعم الأنماط المختلفة (الشكل والمظهر).

    عيوب:

    • تبدأ النافذة التي تحتوي على العديد من المكونات في التباطؤ؛
    • يمكن أن يكون العمل مع مديري التخطيط بمثابة كابوس في الواجهات المعقدة.

    خاتمة:

    لقد عاش سوينغ، سوينغ على قيد الحياة، سوف يعيش سوينغ. على الرغم من أن Oracle تحاول الترويج لـ JavaFX، إلا أن Swing يظل الإطار الأكثر شيوعًا لإنشاء واجهات المستخدم في Java اليوم.

    مجموعة أدوات القطعة القياسية


    كيف
    تبدو
    S.W.T.

    تم تطوير SWT بواسطة شركة IBM في الوقت الذي كان فيه Swing لا يزال بطيئًا، وكان ذلك في المقام الأول لتعزيز بيئة برمجة Eclipse. يستخدم SWT، مثل AWT، مكونات نظام التشغيل، ولكن لديه واجهات تفاعل خاصة به لكل منصة. لذلك، سيتعين عليك لكل نظام جديد تزويد مكتبة JAR منفصلة بالإصدار المناسب من SWT. وهذا جعل من الممكن الاستفادة بشكل كامل من الوظائف الحالية للمكونات في كل محور. تم تنفيذ الميزات والمكونات المفقودة باستخدام ثنائي الأبعاد كما هو الحال في Swing. لدى سبحانه وتعالى العديد من الأتباع، ولكن، يدًا بيد، لا يسع المرء إلا أن يوافق على أن كل شيء لم يكن بالبساطة التي نرغب فيها. سيتعين على المبتدئ أن يقضي وقتًا أطول في تعلم SWT بدلاً من التعرف على Swing. بالإضافة إلى ذلك، يضع SWT مهمة تحرير الموارد على عاتق المبرمج، وبالتالي يجب توخي الحذر بشكل خاص عند كتابة التعليمات البرمجية حتى لا تؤدي الاستثناءات العرضية إلى تسرب الذاكرة.

    مزايا:

    • يستخدم مكونات نظام التشغيل - سرعة أعلى؛
    • يوفر Eclipse محرر نماذج مرئي؛
    • وثائق واسعة النطاق والعديد من الأمثلة؛
    • من الممكن استخدام مكونات AWT وSwing.

    عيوب:

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

    خاتمة:

    ومن الواضح أن شركة آي بي إم حاولت. لكن تبين أن الأمر كان هواة للغاية..

    جافا اف اكس


    يمكن وصف JavaFX بأنه اختراق دون مبالغة. يتم استخدام خط أنابيب الرسومات للعرض، مما يؤدي إلى تسريع التطبيق بشكل كبير. مجموعة المكونات المضمنة واسعة النطاق، بل إن هناك مكونات منفصلة لرسم الرسوم البيانية. يتم تنفيذ دعم محتوى الوسائط المتعددة والعديد من تأثيرات العرض والرسوم المتحركة وحتى اللمس المتعدد. يمكن تغيير مظهر جميع المكونات بسهولة باستخدام أنماط CSS. وأفضل شيء هو أن JavaFX يتضمن مجموعة من الأدوات المساعدة التي تسمح لك بإنشاء مثبت أصلي للأنظمة الأساسية الأكثر شعبية: exe أو msi لنظام التشغيل Windows، أو deb أو rpm لنظام التشغيل Linux، أو dmg لنظام التشغيل Mac. يمكنك العثور على وثائق مفصلة وعدد كبير من الأمثلة الجاهزة على موقع Oracle الإلكتروني. وهذا يجعل البرمجة باستخدام JavaFX سهلة وممتعة.

    مزايا:

    • العمل السريع بسبب خط أنابيب الرسومات.
    • العديد من المكونات المختلفة.
    • دعم الأسلوب؛
    • أدوات مساعدة لإنشاء مثبت البرنامج؛
    • يمكن تشغيل التطبيق كتطبيق سطح مكتب وفي المتصفح كجزء من الصفحة.

    عيوب:

    • لا يزال إطار العمل قيد التطوير، لذلك تحدث أعطال وبعض الأخطاء؛
    • لم يتم استخدام JavaFX على نطاق واسع بعد.

    خاتمة:

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

    المكتبات المرئية في الممارسة العملية

    SWT: القطعة الطقس

    لإظهار إمكانيات المكتبات الرسومية الأكثر شعبية والمبادئ الأساسية للعمل معهم، سنقوم بإنشاء العديد من الأدوات الصغيرة التي تعرض معلومات متنوعة.

    ودعنا نبدأ بالقطعة الأكثر شيوعًا - عرض الطقس الحالي، والتي سنختار سبحانه وتعالى لتنفيذها.

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

    عرض العرض = عرض جديد ()؛ shell = new Shell(display, SWT.NO_TRIM);

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

    تحميل صورة:

    صورة الصورة = صورة جديدة(display, "images/bg.png#26759185");

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

    منطقة المنطقة = منطقة جديدة ()؛ ImageData imageData = image.getImageData(); إذا (imageData.alphaData != null) ( Rectangle Pixel = new Rectangle(0, 0, 1, 1); for (int y = 0; y< imageData.height; y++) { for (int x = 0; x < imageData.width; x++) { if (imageData.getAlpha(x, y) == 255) { pixel.x = imageData.x + x; pixel.y = imageData.y + y; region.add(pixel); } } } } else { ImageData mask = imageData.getTransparencyMask(); Rectangle pixel = new Rectangle(0, 0, 1, 1); for (int y = 0; y < mask.height; y++) { for (int x = 0; x < mask.width; x++) { if (mask.getPixel(x, y) != 0) { pixel.x = imageData.x + x; pixel.y = imageData.y + y; region.add(pixel); } } } }

    ضبط شكل النافذة:

    Shell.setRegion(region);

    الآن نحن بحاجة إلى إنشاء مستمع الحدث للنافذة. سنكون مهتمين بأحداث رسم النافذة، وأحداث الماوس، وأحداث الضغط على المفاتيح بحيث يمكن تحريك النافذة حول الشاشة.

    مستمع المستمع = مستمع جديد () ( int startX, startY; public void HandleEvent(Event e) ( if (e.type == SWT.KeyDown && e.character == SWT.ESC) ( shell.dispose(); ) if (e.type == SWT.MouseDown && e.button == 1) ( startX = e.x; startY = e.y; ) if (e.type == SWT.MouseMove && (e.stateMask & SWT.BUTTON1) != 0 ) ( Point p = shell.toDisplay(e.x, e.y); p.x -= startX; p.y -= startY; shell.setLocation(p); ) if (e.type == SWT.Paint) ( e.gc.drawImage( صورة، imageData.x، imageData.y)؛

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

    لنقم بتعيين مستمع لأحداث النافذة المقابلة:

    Shell.addListener(SWT.KeyDown,listener); shell.addListener(SWT.MouseDown,listener); shell.addListener(SWT.MouseMove,lister); shell.addListener(SWT.Paint,lister);

    اضبط حجم النافذة مساوياً لحجم الصورة:

    Shell.setSize(imageData.x + imageData.width, imageData.y + imageData.height);

    افتح نافذة وابدأ حلقة الحدث:

    Shell.open(); بينما (!shell.isDispose ()) ( إذا (!display.readAndDispatch ()) Display.sleep (); )

    لا تنس تحرير الموارد المستخدمة في النهاية:

    Region.dispose(); image.dispose(); dispose();

    وبتشغيل البرنامج في هذه المرحلة سنحصل على مستطيل يمكن تحريكه بالماوس وإغلاقه باستخدام Esc.

    حان الوقت لإضافة بعض المحتوى. سنعرض الطقس الحالي على شكل أيقونة الحالة (مشمس، مطر، ثلج...)، وقراءات درجة الحرارة ووقت آخر تحديث.

    يتم استخدام مديري التخطيط لترتيب المكونات الرسومية في النافذة بالشكل المطلوب. لا يتعامل مدير التخطيط مع ترتيب المكونات فحسب، بل أيضًا مع تغيير حجمها مع تغير حجم النافذة. بالنسبة لعنصر واجهة المستخدم الخاص بنا، سنستخدم GridLayout. يقوم هذا المدير بوضع المكونات في خلايا جدول وهمي. نقوم بإنشاء GridBagLayout بعمودين بعرض أعمدة مختلف (علامة خاطئة في المنشئ)، وقمنا بتعيينه كمدير تخطيط النافذة:

    تخطيط GridLayout = جديد GridLayout(2, false); shell.setLayout(layout);

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

    // رسم صورة الحالة Label imageLabel = new Label(shell, SWT.NONE); imageLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1));

    تعني الأعلام الموجودة في فئة GridData أن التسمية سيتم وضعها في أعلى اليسار، وسوف تمتد أفقيًا وعموديًا (يتم تعيين الأعلام على true) عندما تكون هناك مساحة خالية، وسوف تشغل صفًا واحدًا وعمودًا واحدًا من جدول التخطيط.

    في SWT لا توجد خلفية شفافة للمكونات، وخلف صورة الحالة ستكون هناك خلفية بيضاء، وهو أمر غير مرغوب فيه بالطبع. لذلك دعونا ننشئ كائنًا ملونًا بلون خلفية النافذة:

    Color bgColor = new Color(display, 0x2b, 0x2b, 0x2b);

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

    ImageLabel.setBackground(bgColor); Image StatusImage = new Image(display, "images/1.png#26759185"); imageLabel.setImage(statusImage);

    الآن دعونا نضيف ملصقًا بدرجة الحرارة الحالية ونضعه في الجزء العلوي الأيمن من النافذة:

    تسمية درجة الحرارة = علامة جديدة (shell، SWT.NONE)؛ thermoLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false, 1, 1));

    دعونا نضبط بعض درجات الحرارة:

    درجة الحرارةLabel.setText("+1 \u2103");

    لتسجيل درجة الحرارة بالدرجة المئوية، يتم استخدام رقم Unicode للحرف المقابل مع أحرف الخدمة \u.

    الخط الافتراضي للتسميات النصية صغير جدًا. لذلك دعونا ننشئ واحدة جديدة أكبر:

    FontData fD = درجة الحرارةLabel.getFont().getFontData(); fD.setHeight(30); fD.setStyle(SWT.BOLD); Font newFont = new Font(display, fD); درجة الحرارةLabel.setFont(newFont); يجب تحرير الخط، مثل كائنات الموارد الأخرى. للقيام بذلك، سوف نستخدم مستمع حدث تدمير التسمية:

    درجة الحرارةLabel.addDisposeListener(new DisposeListener() ( public void widgetDispose(DisposeEvent e) ( newFont.dispose(); ) ));

    وأخيرا، دعونا نضيف تسمية تصف الظروف الجوية:

    وصف التسميةLabel = new Label(shell, SWT.WRAP); descriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 2, 1)); descriptionLabel.setText("غائم جزئيًا، أمطار خفيفة"); descriptionLabel.setBackground(bgColor); descriptionLabel.setForeground(display.getSystemColor(SWT.COLOR_WHITE));

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

    يمكنك الآن إرفاق بعض خدمات الطقس وإنشاء مؤقت للتحديث التلقائي - والأداة جاهزة.

    سوينغ: دائما آخر الأخبار

    سنكتب عنصر واجهة مستخدم في Swing لعرض موجز ويب لـ RSS. نبدأ، كما في المرة السابقة، بإنشاء نافذة. تسمى الفئة التي تنفذ وظيفة النافذة القياسية في Swing JFrame. بشكل افتراضي، لا يؤدي إغلاق نافذة التطبيق في Swing إلى توقف البرنامج، لذا من الأفضل تحديد كيفية تصرف النافذة عند إغلاقها:

    إطار JFrame = جديد JFrame(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    الجدول هو الأفضل لتقديم الأخبار. تم بناء Swing على نمط Model-View-Controller (MVC). في بنية MVC، يوفر النموذج البيانات، ويكون العرض مسؤولاً عن عرض البيانات (مثل النص وحقول الإدخال)، وتوفر وحدة التحكم التفاعل بين النموذج وطريقة العرض. ويوضح الجدول هذا النهج بشكل جيد. لتمثيل البيانات، يتم استخدام فئة تنفذ واجهة TableModel.

    لتخزين معلومات حول الأخبار المتاحة، لنقم بإنشاء فئة FeedMessage تحتوي على حقول لعنوان المقالة وتاريخ النشر:

    رسالة موجزة للطبقة العامة (عنوان السلسلة العامة؛ تاريخ النشر العام؛)

    لتبسيط عملية التطوير وتسريعها، نرث نموذج البيانات الخاص بنا من فئة AbstractTableModel، والتي توفر تنفيذًا جاهزًا لجميع طرق واجهة TableModel تقريبًا.

    يمتد الفصل العام RssFeedTableModel إلى AbstractTableModel (قائمة خاصة الإدخالات = قائمة ArrayList الجديدة<>()؛ تحديث البيانات الفارغة العامة (List الإدخالات) ( this.entries = الإدخالات؛ fireTableDataChanged();) public int getRowCount() ( return inputs.size(); ) public int getColumnCount() ( return 2; ) public Object getValueAt(introwIndex, int columnIndex) (التبديل (columnIndex) (الحالة 0: إرجاع الإدخالات.get(rowIndex).title؛ الحالة 1: إرجاع الإدخالات.get(rowIndex).publicationDate;) إرجاع فارغ؛

    تخبر طريقة fireTableDataChanged العرض بأن نموذج البيانات قد تغير ويحتاج إلى إعادة رسمه.

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

    JTable table = new JTable(new RssFeedTableModel()); table.setShowGrid(false); table.setIntercellSpacing(new Dimension(0, 0)); table.setRowHeight(30); table.setTableHeader(null);

    الآن دعونا نلقي نظرة على مظهر الخلايا. يتيح لك Swing تعيين فئات عرض منفصلة لأنواع البيانات المختلفة. تكون الفئة التي ترث واجهة TableCellRenderer مسؤولة عن عرض خلايا الجدول الفردية. الافتراضي هو DefaultTableCellRenderer، وهو عبارة عن تسمية نصية.

    لنقم بتعيين عارض الخلايا الخاص بنا لبيانات من نوع السلسلة. دعونا نغير لون الخط الافتراضي ونجعل لون الخلفية بديلاً لتحسين إمكانية القراءة.

    Table.setDefaultRenderer(String.class, new DefaultTableCellRenderer() ( اللون الغريب = اللون الجديد (0x25، 0x25، 0x25)؛ اللون المتساوي = اللون الجديد (0x1a، 0x1a، 0x1a)؛ عنوان اللون اللون = اللون الجديد (0x3a، 0xa2، 0xd7) المكون العام getTableCellRendererComponent(جدول JTable، قيمة الكائن، boolean isSelected، boolean hasFocus، int Row، int column) (super.getTableCellRendererComponent(table, value, isSelected, hasFocus, Row, column); setBackground(row % 2 == 0); ?oddColor:evenColor);setForeground(titleColor);

    لكي يبدأ الجدول في استخدام العارض الخاص بنا، نحتاج إلى إضافة طريقة تُرجع نوع البيانات لكل خلية إلى نموذج البيانات:

    الطبقة العامةgetColumnClass(int columnIndex) (التبديل (columnIndex) (الحالة 0: إرجاع String.class؛ الحالة 1: إرجاع Date.class؛) إرجاع Object.class؛)

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

    JScrollPanescrollPane = new JScrollPane(table); table.setFillsViewportHeight(true); scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(0,0));

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

    Frame.getContentPane().add(scrollPane, BorderLayout.CENTER);

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

    JLabel titleLabel = new JLabel("Xakep RSS"); Font titleFont = new Font("Arial", Font.BOLD, 20); titleLabel.setFont(titleFont); titleLabel.setHorizontalAlignment(SwingConstants.CENTER); titleLabel.setForeground(Color.WHITE); titleLabel.setPreferredSize(new Dimension(0, 40)); frame.getContentPane().add(titleLabel, BorderLayout.NORTH);

    على عكس SWT، يتم تحرير كائنات الألوان والخطوط تلقائيًا، لذلك لم يعد هناك ما يدعو للقلق بشأن تسرب الذاكرة.

    قم بإضافة مستمعي الماوس بحيث يمكن تحريك النافذة حول الشاشة.

    MouseAdapter استمع = new MouseAdapter() ( int startX; int startY; public void mousePressed(MouseEvent e) ( if (e.getButton() == MouseEvent.BUTTON1) ( startX = e.getX(); startY = e.getY( )) ) public void mouseDragged(MouseEvent e) ( Point currCoords = e.getLocationOnScreen();frame.setLocation(currCoords.x - startX, currCoords.y - startY); )); titleLabel.addMouseListener(listener); titleLabel.addMouseMotionListener(listener);

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

    Frame.addComponentListener(new ComponentAdapter() ( مكون الفراغ العامResize(ComponentEvent e) (frame.setShape(new RoundRectangle2D.Double(0, 0,frame.getWidth(),frame.getHeight(), 20, 20)); ) ) );

    اضبط حجم النافذة وأزل الإطار واجعل النافذة شفافة.

    Frame.setSize(520, 300); frame.setUndecorated(true); frame.setOpacity(0.85f);

    أخيرًا، نفتح النافذة في دفق الرسومات. SwingUtilities.invocateLater(new Runnable() ( public void run() (frame.setVisible(true); ) ));

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

    JavaFX: دعونا نستمع إلى بعض الموسيقى

    وأخيرًا، أهم ما يميز هذا الموسم هو JavaFX. دعونا نستخدم إمكانات الوسائط المتعددة ومكوناتها للتخطيط وإنشاء معادل بسيط.

    أولا، نحن نرث فئة القطعة من التطبيق. هذه هي فئة التطبيق الرئيسية في JavaFX. يحتوي التطبيق على أساليب دورة حياة التطبيق الرئيسية. يتم إنشاء مكونات النموذج في طريقة البدء، والتي تأخذ فئة Stage كوسيط لها. المرحلة هي نافذة البرنامج. دعونا نغير نمط النافذة إلى شفاف لإزالة الحدود والأزرار. يحتوي المسرح على فئة المشهد، التي تحدد حجم النافذة ولون الخلفية. في المشهد، نجتاز بدورنا فئة المجموعة، والتي سنضع فيها المكونات الفرعية:

    بداية الفراغ العام (المرحلة الأولية) (primaryStage.initStyle (StageStyle.TRANSPARENT)؛ جذر المجموعة = مجموعة جديدة ()؛ مشهد المشهد = مشهد جديد (جذر، 400، 200، Color.TRANSPARENT)؛ PrimaryStage.setScene (مشهد)؛

    لعرض المعادل، نستخدم رسمًا بيانيًا شريطيًا، وسنعرض على طول محاوره التردد وقوة الصوت:

    CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(0,50,10); BarChart قبل الميلاد = BarChart الجديد (س المحور، ص المحور)؛ bc.setPrefSize(400, 200); bc.setLegendVisible(false); bc.setAnimated(false); bc.setBarGap(0); bc.setCategoryGap(1); bc.setVerticalGridLinesVisible(false); bc.setHorizontalGridLinesVisible(false); xAxis.setLabel("التردد"); yAxis.setLabel("الطاقة"); yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis, null, "dB"));

    املأ المخطط بالبيانات الأولية:

    XYChart.Series series1 = XYChart.Series الجديد ()؛ series1Data = new XYChart.Data; فئات السلسلة = سلسلة جديدة؛ ل(int i=0; i (الفئات[i]، 50)؛ series1.getData().add(series1Data[i]); ) bc.getData().add(series1);

    أنشئ مستطيلًا بزوايا مستديرة لمنح الأداة الشكل المناسب:

    مستطيل مستطيل = مستطيل جديد (0، 0، 400، 200)؛ Stop stops = new Stop ( new Stop(0, new Color(0, 0, 0, 0.8)), null); LinearGradient lg2 = LinearGradient(0, 0, 0, 0, false, CycleMethod.NO_CYCLE, stops); مستطيل.setFill(lg2); مستطيل.setArcHeight(20); مستطيل.setArcWidth(20);

    أضف كلا المكونين إلى المجموعة:

    Root.getChildren().addAll(rectangle, bc);

    نقوم بتعيين مستمعي الماوس لمجموعة لتحريك النافذة حول الشاشة:

    Root.setOnMousePressed(new EventHandler () (مقبض الفراغ العام (MouseEvent me) ( initX = me.getScreenX() - PrimaryStage.getX(); initY = me.getScreenY() - PrimaryStage.getY(); ) )); root.setOnMouseDragged(new EventHandler () ( مقبض الفراغ العام (MouseEvent me) ( PrimaryStage.setX(me.getScreenX() - initX); PrimaryStage.setY(me.getScreenY() - initY); ) ));

    قم بتحميل الأغنية في المشغل:

    File file = new File("أخرجني من هنا.mp3"); الوسائط الصوتية Media = null; audioMedia = new Media(file.toURI().toURL().toString()); audioMediaPlayer = new MediaPlayer(audioMedia);

    أضف مستمعًا سيقوم بتحديث المخطط الشريطي:

    AudioMediaPlayer.setAudioSpectrumListener(new AudioSpectrumListener() ( public void SpectrumDataUpdate(طابع زمني مزدوج، مدة مزدوجة، مقادير تعويم، مراحل تعويم) (لـ (int i = 0؛ i< series1Data.length; i++) { series1Data[i].setYValue(magnitudes[i] + 60); } } });

    اجعل المشهد مرئيًا وابدأ الأغنية:

    PrimaryStage.show(); audioMediaPlayer.play();

    بدء تطبيق:

    الفراغ الثابت العام الرئيسي (String args) ( Launch(args); )

    ونحن نتمتع بهذا الجمال.

    تحتوي Java على حزمتين رئيسيتين لإنشاء واجهات المستخدم الرسومية. هذه هي مجموعة أدوات Windows المجردة (AWT) وSwing. يستخدم AWT عناصر واجهة المستخدم لنظام التشغيل، لذا فإن هذه المكتبة أسرع قليلاً. ولكن في رأيي، تم تصميم Swing بشكل أفضل.

    في هذا البرنامج التعليمي، سنلقي نظرة على العناصر الأساسية لمكتبة Swing وسننشئ واجهة بسيطة (GUI) كمثال.

    تُستخدم الحاويات لتجميع مكونات الواجهة. لإنشاء الحاوية الرئيسية لأحد التطبيقات، يتم استخدام حاوية JFrame في أغلب الأحيان (يوجد أيضًا JWindows وJApplet). أسهل طريقة هي الوراثة من JFrame وبالتالي الوصول إلى العديد من الطرق، على سبيل المثال:

    setBounds(x, y, w, h) - يحدد إحداثيات القمة اليسرى العلوية للنافذة، بالإضافة إلى عرضها وارتفاعها.

    setResizable(bool) - يشير إلى ما إذا كان من الممكن تغيير حجم النافذة.

    setTitle(str) - يحدد عنوان النافذة.

    setVisible(bool) - يعرض النافذة بالفعل.

    setDefaultCloseOperation(operation) - يحدد العملية التي سيتم تنفيذها عند إغلاق النافذة.

    الضوابط الأساسية:

    • JLabel - عنصر لعرض النص الثابت؛
    • JTextField - مربع تحرير بسيط؛
    • JButton - الزر العادي (زر)؛
    • JCheckBox - عنصر التحديد (مشابه لمربع الاختيار)؛
    • JRadioButton - زر الاختيار

    كما ترون، كل شيء بسيط جدا ومنطقي.

    عند عرض عناصر التحكم، يتم استخدام مديرين خاصين - LayoutManager. لدى جميع LayoutManagers طرق لإضافة العناصر وإزالتها.

    FlowLayout - يستخدم لعرض العناصر بالتسلسل. إذا لم يكن هناك عنصر مناسب في سطر معين، فسيظهر في العنصر التالي.

    GridLayout - يعرض العناصر على شكل جدول بنفس أحجام الخلايا.

    BorderLayout - يُستخدم عند عرض ما لا يزيد عن 5 عناصر. توجد هذه العناصر على طول حواف الإطار وفي المنتصف: الشمال والجنوب والشرق والغرب والوسط.

    BoxLayout - يعرض العناصر الموجودة في صف أو عمود.

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

    ومن الجدير أيضًا الاهتمام بالتعامل مع الأحداث. ولهذا الغرض، يتم استخدام ما يسمى بمستمعي الأحداث.

    حسنًا، ما يكفي من النظرية، دعنا ننتقل إلى مثال واجهة المستخدم الرسومية:

    استيراد java.awt.*; import java.awt.event.*; استيراد javax.swing.*; الطبقة العامة SimpleGUI تمتد JFrame (زر JButton الخاص = JButton الجديد ("اضغط")؛ إدخال JTextField الخاص = JTextField الجديد (""، 5)؛ تسمية JLabel الخاصة = JLabel الجديد ("Input:")؛ JRadioButton الخاص radio1 = JRadioButton الجديد ("اختر هذا"); Private JRadioButton radio2 = new JRadioButton("اختر ذلك"); public JCheckBox check = new JCheckBox("Check", false public SimpleGUI() ( super("مثال بسيط"); this.setBounds (100,100,250,100); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); حاوية الحاوية = this.getContentPane(); حاوية.setLayout(3,2,2,2)); radio2.radio1.setSelected(true);container.add( check); ""؛ message += "تم الضغط على الزر\n"; message += "النص هو" + input.getText() + "\n"; message += (radio1.isSelected()؟"Radio #1": "Radio #2") + " is Selected\n"; message += "CheckBox is " + ((check.isSelected()) ?checked": "unchecked"); JOptionPane.showMessageDialog(null, message, "Output", JOptionPane.PLAIN_MESSAGE); ) ) public static void main(String args) ( تطبيق SimpleGUI = new SimpleGUI(); app.setVisible(true); ) )

    ملحوظات:

    يقوم getContentPane بإرجاع حاوية المستوى الأعلى. يتم استخدام ButtonGroup لإنشاء مجموعة من أزرار الاختيار المترابطة.

    تنفذ الطبقة الداخلية ButtonActionListener واجهة ActionListener. للقيام بذلك، تحتاج إلى توفير تنفيذ الأسلوب actionPerformed.

    يتم استخدام JOptionPane لعرض مربعات الحوار.

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

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

    إذن ما هي الأدوات التي نحتاجها:

    • جهاز جافا الظاهري (OpenJDK أو Oracle JDK)
    • Intellij IDEA (أو Java IDE آخر)

    بعد تثبيت البرنامج الضروري، افتح فكرة ذكيةوقم بإنشاء مشروع جديد: ملف -> مشروع جديد...

    لقد قمت بتسمية المشروع guiBase. كما ترون في الصورة، المجلد srcلا يحتوي على أي شيء، لذلك قمنا بإنشاء فئتنا الرئيسية التي تحتوي على الوظيفة رئيسي.

    الطبقة العامة الرئيسية ( public static void main(String args) ( System.out.println("Hello, Govzalla!"); ) )

    يمكنك رؤية محتويات الفصل الرئيسي أعلاه. يمكننا الآن إنشاء مشروع ( بناء المشروع ) وتشغيله ( يجري ). أسفل في المحطة الخاصة بك بيئة تطوير متكاملةسترى رسالة "مرحبًا يا جوفزاللا!". ولكن كما فهمت أنت بنفسك، فهو لا يدعم واجهة المستخدم الرسومية.

    في هذه المرحلة لدينا بالفعل برنامج عمل، ولكن بدون دعم واجهة المستخدم الرسومية. والآن في نفس المجلد srcدعونا نخلق نموذج واجهة المستخدم الرسومية: جديد -> نموذج واجهة المستخدم الرسومية

    افتح نموذج واجهة المستخدم الرسومية الذي تم إنشاؤه، وانقر فوق JPanelوتعيين معرفه في الحقل اسم الحقل، انا سألت لوحة.

    ثم اسحبه إلى النموذج الموجود على الجانب الأيمن JTextField, JpasswordFieldو جيبوتون:

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

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

    حاليا لدينا النموذج النافذة الرئيسيةوالطبقة النافذة الرئيسيةممتد مع JFrame. نحن الآن بحاجة إلى تحديد كافة عناصر واجهة المستخدم الرسومية المضافة كمحتوى للفئة النافذة الرئيسية
    this.getContentPane().add(panel);
    وبعد ذلك سيتم تغيير محتويات الملف MainWindow.java على النحو التالي:

    استيراد javax.swing.*; يقوم MainWindow للطبقة العامة بتوسيع JFrame (خاص JTextField textField1؛ خاص JPasswordFieldpasswordField1؛ خاص JButton Button1؛ لوحة JPanel خاصة؛ public MainWindow() ( this.getContentPane().add(panel); ) )

    إذا حاولت تشغيل الكود، فسترى نفس الرسالة "Hello, Govzalla!" الحقيقة هي أننا أنشأنا فئة ونموذجًا لها، لكننا لم نقم بإنشاء مثيل لهذه الفئة.

    حان الوقت لتغيير ملف Main.java وإضافة الكود لإنشاء واجهة المستخدم الرسومية الخاصة بنا هناك:

    استيراد java.awt.*; public class Main ( public static void main(String args) ( // إنشاء مثيل لفئة MainWindow MainWindow mainWindow = new MainWindow(); // حزم جميع العناصر من النموذج mainWindow.pack(); // تغيير حجم النافذة mainWindow.setSize( new Dimension(200, 200)); // عرض النافذة التي تم إنشاؤها mainWindow.setVisible(true)) )

    تشغيل الكود

    بالضغط على زر Button، ستلاحظ أن البرنامج لا يستجيب على الإطلاق. الشيء هو أننا لم نضيف المستمع بعد ( المستمع) للمناسبات ( الأحداث) زر زر.

    مستمع الحدث ( مستمع الحدث) جيبوتونيجب أن يكون محول زرع ActionListenerلذلك دعونا نضيف الكود التالي إلى نص الفصل النافذة الرئيسية:

    الطبقة الخاصة MyButtonListener تنفذ ActionListener ( @Override public void actionPerformed(ActionEvent actionEvent) ( ) )

    طريقة العمل المؤدى() سيعالج جميع أحداث Button1، ولكن أولاً لا تزال بحاجة إلى إخبار Button1 بالفئة التي سيعالجها، لذا أضف التعليمة البرمجية التالية إلى مُنشئ فئة MainWIndow:
    this.button1.addActionListener(new MyButtonListener());
    لمنع معالجنا من أن يكون بلا معنى، أضف الكود التالي إلى الطريقة العمل المؤدى():

    @Override public void actionPerformed(ActionEvent actionEvent) ( if (textField1.getText().equals(passwordField1.getText())) ( JOptionPane.showMessageDialog(null, "Success"); ) else ( JOptionPane.showMessageDialog(null, "Failure "");)

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

    تاريخيًا، كان علي أن أعمل قليلًا جدًا مع واجهة المستخدم. على ما يبدو، هذا هو السبب في أن جميع أنواع Qt وwxWidgets مثيرة للاهتمام للغاية بالنسبة لي - كل شيء يبدو جديدًا ومثيرًا للاهتمام وغير عادي. ومع ذلك، منذ أن بدأت تعلم Java، اليوم لن نتحدث عن Qt أو wxWidgets، ولكن عن Swing. اليوم، سنكتب معًا تطبيقًا بسيطًا لواجهة المستخدم الرسومية بلغة Java، مع أزرار وقوائم وحتى تطبيق يمكنه تغيير الأشكال!

    الوضع مع أطر عمل واجهة المستخدم الرسومية في عالم Java مربك إلى حد ما. بقدر ما أستطيع أن أفهم، الأمور هي على النحو التالي.

    • ايه دبليو تي.(مجموعة أدوات النافذة المجردة) كان أول إطار عمل لواجهة المستخدم الرسومية. كانت الفكرة صحيحة - تستخدم AWT عناصر تحكم أصلية، أي أنها تبدو أصلية وفعليًا، بغض النظر عن مكان تشغيل التطبيق الخاص بك. لسوء الحظ، اتضح أن (1) هناك عدد قليل من عناصر التحكم المشتركة في بيئات مختلفة و(2) من الصعب جدًا كتابة واجهات أصلية عبر الأنظمة الأساسية بحيث لا يزحف أي شيء أو يتحرك بعيدًا؛
    • لذلك، تم استبدال AWT بـ يتأرجح. يستخدم Swing النماذج التي أنشأتها AWT، والتي يرسم عليها عناصر التحكم من تلقاء نفسه. يعمل هذا المرفق، بطبيعة الحال، بشكل أبطأ، ولكن واجهة المستخدم تصبح أكثر قابلية للنقل. يقدم Swing للمبرمج مجموعة متنوعة من الشكل والمظهر للاختيار من بينها، والتي بفضلها يمكنك إما جعل التطبيق يبدو كما هو وتصرفنفس الشيء على كل من Windows وLinux، أو بحيث يكون التطبيق مشابهًا جدًا للتطبيق الأصلي، بغض النظر عن مكان تشغيله. في الحالة الأولى، يكون تصحيح التطبيق أسهل، وفي الحالة الثانية، يصبح المستخدمون أكثر سعادة. بالمناسبة، تم إنشاء Swing في الأصل بواسطة فريق Netscape؛
    • S.W.T.(Standard Widget Toolkit) هو إطار عمل كتبته شركة IBM ويستخدم في Eclipse. كما هو الحال في AWT، يتم استخدام عناصر التحكم الأصلية. SWT ليس جزءًا من JDK ويستخدم JNI، لذا فهو لا يتناسب حقًا مع أيديولوجية Java "الكتابة مرة واحدة، والتشغيل في كل مكان". يبدو أنه إذا كنت تريد ذلك حقًا، فيمكنك حزم تطبيق SWT للجميع، وجميع الأنظمة الأساسية، ومن ثم يبدو أن التطبيق أصبح محمولًا، ولكن فقط حتى يظهر نظام تشغيل جديد أو بنية معالج؛
    • جافا اف اكسيتم نشره بشكل نشط في Oracle ويتم وضعه كبديل سريع لـ Swing. من الناحية الأيديولوجية، JavaFX يشبه Swing، أي أن عناصر التحكم ليست أصلية. من بين الميزات المثيرة للاهتمام في JavaFX هي تسريع الأجهزة، وإنشاء واجهة المستخدم الرسومية باستخدام CSS وXML (FXML)، والقدرة على استخدام عناصر تحكم JavaFX في Swing، بالإضافة إلى مجموعة من عناصر التحكم الجميلة الجديدة، بما في ذلك رسم المخططات والرسوم البيانية ثلاثية الأبعاد. يتوفر فيديو يحتوي على نظرة عامة أكثر تفصيلاً عن JavaFX. منذ Java 7، أصبحت JavaFX جزءًا من JRE/JDK؛
    • منصة نت بينز(يجب عدم الخلط بينه وبين NetBeans IDE!) - هذا شيء، كما أفهمه، يعمل فوق Swing وJavaFX، ويوفر واجهة أكثر ملاءمة للعمل معهم، بالإضافة إلى جميع أنواع عناصر التحكم الإضافية. في أحد التطبيقات التي تستخدم منصة NetBeans، رأيت القدرة على المخدرات وإسقاط علامات التبويب، وترتيب اللوحات في النافذة بطريقة مماثلة لمديري النوافذ المتجانبة. على ما يبدو، فإن التأرجح نفسه لا يستطيع القيام بذلك. اقرأ المزيد عن منصة NetBeans؛

    من الممكن أن تكون هناك أطر أخرى. الأكثر شهرة اليوم هو Swing، وهذا ما سنفعله.

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

    سيبدو تطبيقنا هكذا ضمن Ubuntu:

    وهذه هي الطريقة التي سيبدو بها عند التشغيل تحت نظام Windows:

    كما ترون، تشتمل JREs لنظامي التشغيل Windows وLinux على مجموعة مختلفة من L&F. بالإضافة إلى ذلك، يمكنك توصيل موقع Look&Feel التابع لجهة خارجية أو حتى كتابة ملف خاص بك. افتراضيًا، يتم استخدام L&F Metal، والذي يبدو متماثلًا تقريبًا في جميع أنظمة التشغيل ومديري النوافذ. إذا كنت تفضل الأزرار المستديرة، فيمكنك استخدام Look&Feel Nimbus بدلاً من Metal. إذا كنت تريد أن يبدو التطبيق وكأنه تطبيق أصلي، فيجب عليك اختيار L&F GTK+ بالنسبة لنظام التشغيل Linux (أتساءل، ماذا لو كان المستخدم يستخدم KDE؟)، وبالنسبة لنظام التشغيل Windows - L&F Windows. قد تكون فكرة جيدة أن تدرج في برنامجك القدرة على التبديل بين L&F المختلفة. من ناحية أخرى، سيتعين عليك اختبار التطبيق مع كل هذه L&F.

    دعونا نلقي نظرة على الكود المصدري للتطبيق. أكد لي زملائي المتخصصين في واجهة المستخدم أنهم لا يستخدمون أي محررات WYSIWYG، وإذا كانوا يستخدمونها، فعندئذٍ فقط للنماذج الأولية السريعة. أحد محرري WYSIWYG الجيدين كان يُدعى JFormDesigner. يقولون أن الكود الذي ينشئه يشبه الكود الذي كتبه شخص ما، وليس الجهنمية().sequence().calls().methods(). بشكل عام، تمت كتابة كافة التعليمات البرمجية باستخدام IntelliJ IDEA.

    الفراغ العام الثابت الرئيسي (وسائط السلسلة) (

    @تجاوز
    تشغيل الفراغ العام () (
    createGUI() ;
    }
    } ) ;
    }

    في Swing وAWT، إذا أردنا تغيير شيء ما في واجهة المستخدم، فيجب علينا القيام بذلك من خلال سلسلة إرسال الحدث. تأخذ الطريقة الثابتة التي تستدعي لاحقًا فئة تنفذ الواجهة القابلة للتشغيل وتستدعي طريقة التشغيل () الخاصة بها داخل مؤشر ترابط إرسال الحدث. إذا لم تكن على دراية بالصيغة المذكورة أعلاه، فهي طريقة في Java للإعلان عن فئة دون إعطائها اسمًا. تسمى الفصول بدون اسم مجهولة. في كثير من الأحيان، تؤدي الفئات المجهولة في Java نفس الدور الذي تؤديه وظائف lambda في لغات البرمجة الوظيفية. من بين أمور أخرى، يتم دعم عمليات الإغلاق أيضًا. ومن المثير للاهتمام، على عكس lambdas، تسمح لك الفئات المجهولة في Java بتمرير مجموعة من الأساليب في وقت واحد. علاوة على ذلك، بمساعدة الميراث والفئات المجردة، يمكنك تنفيذ التنفيذ الافتراضي لجميع الطرق أو جزء منها.

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

    نتيجة لذلك، سيستدعي مؤشر ترابط إرسال الحدث طريقة createGUI()، ويكون رمزها الكامل كما يلي:

    إنشاء واجهة المستخدم الرسومية () باطلة ثابتة خاصة (
    قائمة J< String>القائمة = قائمة J الجديدة<> () ;
    list.setSelectionMode (ListSelectionModel .SINGLE_SELECTION)؛

    JScrollPane listScrollPane = new JScrollPane(list);

    JPanel topPanel = new JPanel();
    topPanel.setLayout(new BorderLayout());
    topPanel.add (listScrollPane, BorderLayout . CENTER ) ;

    ActionListener updateButtonListener = new UpdateListAction(list) ;
    updateButtonListener.actionPerformed(
    حدث ActionEvent جديد (قائمة، ActionEvent .ACTION_PERFORMED، null )
    ) ;

    JButton updateListButton = new JButton("قائمة التحديث");
    JButton updateLookAndFeelButton = new JButton ("Update Look&Feel")؛

    JPanel btnPannel = new JPanel () ؛
    btnPannel.setLayout(new BoxLayout(btnPannel, BoxLayout.LINE_AXIS));
    btnPanel.add (updateListButton)؛
    btnPannel.add(Box.createHorizontalStrut(5));
    btnPannel.add (updateLookAndFeelButton) ؛

    JPanel BottomPanel = new JPanel();
    BottomPanel.add(btnPannel) ;

    لوحة JPanel = new JPanel();
    Panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    Panel.setLayout(new BorderLayout());
    Panel.add (topPanel, BorderLayout . CENTER ) ;
    Panel.add(bottomPanel, BorderLayout.SOUTH);

    إطار JFrame = JFrame جديد ("Look&Feel Switcher")؛
    frame.setMinimumSize(new Dimension(300, 200));
    frame.setDefaultCloseOperation (WindowConstants .EXIT_ON_CLOSE) ؛
    Frame.add(panel) ;
    frame.pack();
    frame.setVisible(true);

    UpdateListButton.addActionListener(updateButtonListener) ;
    updateLookAndFeelButton.addActionListener (
    UpdateLookAndFeelAction الجديد (الإطار، القائمة)
    ) ;
    }

    بشكل عام، لا يوجد شيء معقد للغاية هنا. يتم إنشاء الأزرار، وإنشاء القائمة، ويتم تغليف القائمة في JScrollPane بحيث يتم تمرير القائمة. توجد عناصر التحكم في الإطار باستخدام اللوحات. يمكن أن تحتوي اللوحات على تخطيطات مختلفة، وهنا استخدمنا BorderLayout وBoxLayout. المبدأ مشابه لذلك المستخدم في wxWidgets.

    للرد على الأحداث المختلفة، مثل النقرات على الأزرار، يتم استخدام الفئات التي تنفذ واجهة ActionListener. يستخدم الكود أعلاه فئتين من هذا القبيل - UpdateListAction وUpdateLookAndFeelAction. كما يمكنك تخمين الاسم بسهولة، فإن الفئة الأولى مسؤولة عن معالجة النقرات على الزر الأيسر "تحديث القائمة"، والثانية - على الزر الأيمن "تحديث الشكل والمظهر". يرتبط ActionListeners بالأزرار باستخدام طريقة addActionListener. نظرًا لأننا نرغب في رؤية قائمة بالشكل والمظهر المتاحين بعد تشغيل التطبيق مباشرة، فإننا نحاكي النقر على زر "تحديث القائمة". للقيام بذلك، نقوم بإنشاء مثيل لفئة ActionEvent وتمريره كوسيطة إلى الأسلوب actionPerformed لفئة UpdateListAction.

    تنفيذ فئة UpdateListAction كما يلي:

    فئة ثابتة UpdateListAction تنفذ ActionListener (
    قائمة J الخاصة< String>قائمة؛

    UpdateListAction العام (JList< String>قائمة) (
    هذه القائمة = القائمة؛
    }

    @تجاوز
    إجراء باطل عام تم تنفيذه (حدث ActionEvent) (
    ArrayList< String>lookAndFeelList = new ArrayList<> () ;
    UIManager.LookAndFeelInfoمعلومات المصفوفة =

    int lookAndFeelIndex = 0 ;
    كثافة العمليات الحاليةLookAndFeelIndex = 0 ;
    السلسلة الحاليةLookAndFeelClassName =
    UIManager .getLookAndFeel() .getClass() .getName();

    ل ( UIManager.LookAndFeelInfoمعلومات: معلومات صفيف) (
    إذا (info.getClassName().equals(currentLookAndFeelClassName)) (
    currentLookAndFeelIndex = lookAndFeelIndex;
    }
    lookAndFeelList.add(info.getName());
    lookAndFeelIndex++;
    }

    String listDataArray = new String [ lookAndFeelList.size () ] ;
    السلسلة النهائية newListData =
    lookAndFeelList.toArray(listDataArray) ;
    Final int newSelectedIndex = currentLookAndFeelIndex;

    SwingUtilities.invocLater(جديد Runnable()(
    @تجاوز
    تشغيل الفراغ العام () (
    list.setListData(newListData);
    list.setSelectedIndex(newSelectedIndex) ;
    }
    } ) ;
    }
    }

    يقوم المُنشئ بتمرير مؤشر إلى القائمة التي سنعرض فيها الشكل والمظهر المتوفرين. في الواقع، نظرًا لأن UpdateListAction عبارة عن فئة متداخلة من فئة LookAndFeelSwitcher الرئيسية، فإنها تتمتع بالقدرة على الوصول مباشرة إلى حقول مثيل LookAndFeelSwitcher الذي قام بإنشائها. لكن الجانب الوظيفي بداخلي يقاوم هذا النهج، لذلك قررت تمرير إشارة إلى القائمة بشكل صريح من خلال المُنشئ.

    سيتم استدعاء الأسلوب actionPerformed عند النقر فوق الزر. يعد رمز هذه الطريقة تافهًا تمامًا - فنحن ببساطة نستخدم الأساليب الثابتة لفئة UIManager للحصول على قائمة بالشكل والمظهر المتاحين، بالإضافة إلى تحديد الشكل والمظهر الحالي. يتم بعد ذلك تحديث محتويات القائمة والعنصر المحدد فيها. هنا عليك الانتباه إلى نقطتين. أولاً، كل مظهر ومظهر له اسمو اسم الفصلهذه أشياء مختلفة. يجب علينا إظهار الأسماء للمستخدم، وعند تبديل الشكل والمظهر، استخدم اسم الفئة. ثانيًا، لاحظ كيف يتم إنشاء المتغيرات النهائية newListData وnewSelectedIndex ثم استخدامها في الفئة المجهولة. وهذا هو نفس نظير عمليات الإغلاق التي تمت مناقشتها سابقًا. ومن الواضح أن استخدام المتغيرات غير النهائية في عمليات الإغلاق سيؤدي إلى عواقب وخيمة.

    أخيرًا، دعونا نلقي نظرة على فئة UpdateLookAndFeelAction:

    فئة ثابتة UpdateLookAndFeelAction تنفذ ActionListener (
    قائمة J الخاصة< String>قائمة؛
    إطار جذر JFrame خاص؛

    UpdateLookAndFeelAction العام (إطار JFrame، JList< String>قائمة) (
    هذا .rootFrame = الإطار؛
    هذه القائمة = القائمة؛
    }

    @تجاوز
    إجراء باطل عام تم تنفيذه (ActionEvent e) (
    String lookAndFeelName = list.getSelectedValue();
    UIManager.LookAndFeelInfoمعلومات المصفوفة =
    UIManager.getInstalledLookAndFeels();

    ل ( UIManager.LookAndFeelInfoمعلومات: معلومات صفيف) (
    إذا (info.getName().equals(lookAndFeelName)) (
    String message = "تم تغيير الشكل والمظهر إلى" + lookAndFeelName;
    يحاول (
    UIManager.setLookAndFeel(info.getClassName());
    SwingUtilities .updateComponentTreeUI (rootFrame) ؛
    ) قبض على (ClassNotFoundException e1) (
    message = "خطأ:" + info.getClassName() + "غير موجود"؛
    ) قبض على (InstantiationException e1) (
    الرسالة = "خطأ: استثناء إنشاء مثيل";
    ) قبض على (IllegalAccessException e1) (
    message = "خطأ: وصول غير قانوني" ;
    ) يمسك ( UnsupportedLookAndFeelExceptionه1)(
    الرسالة = "خطأ: الشكل والمظهر غير مدعومين";
    }
    JOptionPane .showMessageDialog (null , message) ;
    استراحة ؛
    }
    }
    }
    }

    نحن هنا ببساطة (1) نجد L&F باسم يساوي الاسم المحدد في القائمة، (2) نغير L&F باستخدام طريقة setLookAndFeel الثابتة لفئة UIManager، و(3) نعيد رسم الإطار الرئيسي لواجهة المستخدم الخاصة بنا، كما بالإضافة إلى العناصر الموجودة عليه بشكل متكرر، وذلك باستخدام الأسلوب الثابت updateComponentTreeUI لفئة SwingUtilities. وأخيرًا، نقوم بإخطار المستخدم برسالة إذا كان كل شيء ناجحًا.

    أود أيضًا أن أقول بضع كلمات حول تصحيح أخطاء تطبيقات واجهة المستخدم الرسومية في Java، وليس واجهة المستخدم الرسومية فقط. أولاً، يوجد في Swing اختصار لوحة المفاتيح السحري Ctr + Shift + F1، والذي يعرض معلومات حول كيفية تحديد موقع عناصر التحكم في stdout. مفيد جدًا إذا كنت تريد سرقة واجهة المستخدم من منافسيك. ثانيا، هناك مثل هذا المفتاح السريع المثير للاهتمام Ctr + \. إذا قمت بالنقر فوقه في وحدة التحكم الخاصة بتطبيق Java قيد التشغيل، فسيتم عرض جميع سلاسل الرسائل وتتبعات المكدس الخاصة بها. مناسب إذا وصلت إلى طريق مسدود. أخيرًا، أثناء تطوير واجهة المستخدم الرسومية، قد يكون من المفيد تزيين اللوحات بألوان مختلفة. يمكنك القيام بذلك على النحو التالي:

    ButtonPanel.setBackground(Color.BLUE);