نافذتك الأولى في JavaFX
نافذتك الأولى في JavaFX
قدّمت الدروس السابقة فئة Application ودورة الحياة وشجرة العقد التي تُشكّل المشهد. الآن تجمع كل ذلك في نافذة حقيقية تعمل ويستطيع المستخدم التفاعل معها. بنهاية هذا الدرس سيكون لديك تطبيق JavaFX يعرض زرًا ويستجيب حين ينقر عليه المستخدم — أصغر برنامج واجهة رسومية ذي معنى يمكنك كتابته.
ما يحتاجه وقت التشغيل منك
تشترط JavaFX امتداد فئة واحدة تحديدًا من javafx.application.Application وتجاوز الدالة start(Stage primaryStage). هذه الدالة هي نقطة دخولك إلى عالم الواجهات الرسومية. كل ما يلمس شجرة المشهد يجب أن يحدث هنا أو على خيط تطبيق JavaFX (يُغطّى بالكامل في الدرس التالي). أما دالة main فتستدعي launch(args) فقط لتسليم التحكم إلى الأداة.
main كليًا عند تهيئة نظام الوحدات — لكن إبقاءها أكثر أمانًا وتوافقًا عبر أدوات البناء المختلفة.
بناء المشهد خطوة بخطوة
تُبنى نافذة JavaFX من الأسفل إلى الأعلى: تُنشئ عناصر التحكم أولًا، ثم تجمعها في حاوية تخطيط، ثم تلفّها في Scene، وأخيرًا تضع المشهد على Stage. إليك البرنامج الكامل:
لنتجوّل عبر كل قرار في هذا البرنامج المكوّن من 30 سطرًا.
الخطوة 1 — عناصر التحكم مجرد كائنات
كلٌّ من Label وButton فئات فرعية من Node. تُنشئها بـnew، وتضبط خصائصها بالمُعيِّنات (setters)، وتضيفها إلى حاوية أب. لا يوجد XML ولا ملف وصفي ولا معالج IDE مطلوب — هو بناء كائنات Java خالص.
الخطوة 2 — الاستجابة لحدث باستخدام Lambda
السطر button.setOnAction(event -> label.setText("Hello, JavaFX!")) هو جوهر برمجة الواجهات الرسومية: ربط فعل المستخدم بقطعة كود. تقبل setOnAction أي EventHandler<ActionEvent>. ولأن هذه الواجهة وظيفية (دالة مجردة واحدة)، تعمل lambda بشكل مثالي. عند النقر على الزر يستدعي الإطار هذه lambda على خيط تطبيق JavaFX، وهو أيضًا الخيط المالك لشجرة المشهد — لذا تحديث label مباشرةً آمن هنا.
الخطوة 3 — حاويات التخطيط تضع العناصر في أماكنها
يرصّ VBox عناصره الأبناء عموديًا مع مسافة قابلة للضبط. الوسيطة الأولى لمنشئه هي المسافة بالبكسل بين العناصر. يمكنك أيضًا ضبط التبطين والمحاذاة عبر CSS المضمّنة (أسماء الخصائص -fx-*) أو عبر واجهة Java البرمجية. من الحاويات الشائعة الأخرى التي ستلتقيها قريبًا: HBox (أفقي)، وBorderPane (شمال/جنوب/شرق/غرب/مركز)، وGridPane (صفوف وأعمدة).
تُضيف الأبناء بـgetChildren().addAll(...). تُعيد دالة getChildren() قائمة ObservableList<Node> — إضافة العناصر أو إزالتها منها تُفعّل تلقائيًا دورة تخطيط وإعادة رسم.
الخطوة 4 — المشهد يمتلك عقدة جذر وحجمًا
ينشئ new Scene(root, 320, 200) مشهدًا جذره هو VBox وحجمه الأولي 320×200 بكسل. كل عنصر تحكم داخل root هو الآن جزء من شجرة عقد هذا المشهد. كائن Scene هو أيضًا المكان الذي تُرفق فيه أوراق الأنماط لاحقًا:
الخطوة 5 — الخشبة هي نافذة نظام التشغيل
يوفّر الإطار primaryStage حين يستدعي start. تضبط عنوانًا وتُرفق المشهد وتستدعي show(). هذا كل ما يلزم لعرض نافذة على الشاشة. الخشبة هي أيضًا المكان الذي تتحكم فيه في قابلية تغيير الحجم والوضع ملء الشاشة والأيقونات والأبعاد الدنيا/القصوى:
الرسم البياني الكامل للكائنات
بعد show() يبدو الرسم البياني الحي للكائنات هكذا:
هذه شجرة المشهد في العمل. حين تنقر الزر تتغير خاصية نص التسمية؛ تلاحظ محرك الرسم في JavaFX التغيير (لأن Text قابل للمراقبة) ويُعيد رسم المنطقة المتأثرة فقط في النبضة التالية — دون استدعاءات إعادة رسم يدوية.
سلوك الإغلاق
بشكل افتراضي، إغلاق الخشبة الرئيسية يُنهي التطبيق عبر Platform.exit(). إذا كان لديك خشبات متعددة أو تحتاج تنفيذ كود تنظيف، يمكنك تجاوز stop() في فئتك الفرعية من Application:
System.exit() أبدًا لإغلاق تطبيق JavaFX. تتجاوز هذه الدالة stop() وتتخطى أي تنظيف سجّلته. استخدم Platform.exit() بدلًا من ذلك، أو أغلق النافذة ببساطة ودع السلوك الافتراضي يعمل.
تشغيل التطبيق
مع توفّر JavaFX SDK في مسار الوحدات (مثلًا عبر تبعية Maven/Gradle org.openjfx:javafx-controls)، صرّف التطبيق وشغّله كفئة Java عادية. يدعم كل من IntelliJ IDEA وVS Code مشاريع JavaFX من خلال تكاملهما مع Maven/Gradle — لا تحتاج إضافة منفصلة لهذا الإعداد الأساسي.
الخلاصة
تحتاج نافذة JavaFX العاملة إلى خمسة أشياء: عناصر تحكم مُنشأة ككائنات، ومعالج حدث يربط أفعال المستخدم بالكود، وحاوية تخطيط تجمع العناصر، ومشهد Scene يمنح الشجرة حجمًا، وخشبة Stage تعرضها على الشاشة. يستدعي وقت التشغيل start() نيابةً عنك — مهمتك هي بناء الشجرة واستدعاء show(). هذا النمط يتوسّع دون تغيير من هذا البرنامج المكوّن من 30 سطرًا إلى تطبيق مؤسسي متعدد الشاشات.