فئة Application ودورة حياة التطبيق
فئة Application ودورة حياة التطبيق
يدور كل برنامج JavaFX حول فئة مجردة واحدة هي javafx.application.Application. إن الوراثة منها وتنفيذ أسلوبها المجرد start() هو الحدّ الأدنى المطلوب لعرض نافذة على الشاشة. لكن فئة Application تفعل أكثر بكثير من مجرد استدعاء start() — فهي تُدير دورة حياة متسلسلة بعناية تُهيّئ أدوات الواجهة الرسومية، وتُسلّم التحكم لكودك على الخيط الصحيح، وتُنهي كل شيء بشكل نظيف عند إغلاق المستخدم آخر نافذة. إن فهم دورة الحياة هذه هو ما يُميّز مطوّر JavaFX عن شخص نسخ مثال "Hello World" ببساطة.
أساليب دورة الحياة الثلاثة
تُعرّف فئة Application ثلاثة أساليب قابلة للتجاوز تُستدعى بترتيب مضمون:
init()— يُستدعى مرةً واحدة على خيط المشغّل (Launcher Thread) قبل إنشاء الواجهة الرسومية. تجاوَزه لتحميل الإعدادات أو فتح اتصالات قاعدة البيانات أو أي عمل مكثّف لا يلمس عُقد الواجهة. التنفيذ الافتراضي لا يفعل شيئًا.start(Stage primaryStage)— يُستدعى على خيط تطبيق JavaFX (خيط الواجهة). هذا هو الأسلوب المجرد الوحيد؛ ويجب عليك تنفيذه. بحلول وقت استدعائه تكون أدوات الواجهة قد هُيِّئت بالكامل ويكون آمنًا إنشاء كائناتStageوSceneوعرضها. المعاملprimaryStageهو النافذة الرئيسية التي يوفّرها النظام.stop()— يُستدعى مرةً واحدة على خيط تطبيق JavaFX بعد إغلاق آخر نافذة (أو بعد استدعاءPlatform.exit()). تجاوَزه لتحرير الموارد — إغلاق مؤشرات الملفات، وإيقاف الخيوط الخلفية، وتفريغ ذاكرة التخزين المؤقت. التنفيذ الافتراضي لا يفعل شيئًا.
init() على خيط المشغّل — لا يمكنك إنشاء Stage أو أي عقدة واجهة هناك. يعمل start() وstop() على خيط تطبيق JavaFX — جميع عمليات الواجهة تنتمي هنا. انتهاك هذه القواعد يتسبب في رمي IllegalStateException أثناء التشغيل.
أسلوب launch()
المهمة الحقيقية الوحيدة لأسلوب main() هي استدعاء Application.launch(). هذا الأسلوب الساكن:
- يُشغّل أدوات JavaFX وخيط معالجة الأحداث الخاص بها.
- يُنشئ نسخة من الفئة الفرعية
Applicationالخاصة بك (باستخدام مُنشئها الذي لا يقبل معاملات). - يستدعي
init()على خيط المشغّل. - يستدعي
start(primaryStage)على خيط تطبيق JavaFX. - يُحجب حتى يخرج التطبيق.
- يستدعي
stop()على خيط تطبيق JavaFX.
الشكل الأكثر شيوعًا يمرّر حرفية الفئة وأي وسيطات سطر أوامر:
عند الاستدعاء من داخل الفئة الفرعية Application نفسها، التحميل الزائد الذي يُحذف فيه اسم الفئة يُعادل ذلك:
--add-modules javafx.controls,javafx.fxml إلى JVM. استدعاء Application.launch() نفسه لم يتغيّر — التغيير في طريقة تشغيل JVM لا في الكود.
تطبيق بسيط — بشرح مفصّل
القائمة أدناه هي أصغر برنامج JavaFX كامل. اقرأ كل تعليق بعناية؛ لكل سطر سبب وجيه للوجود.
تمرير معاملات إلى تطبيقك
أي سلاسل نصية تُمرَّر بعد اسم الفئة في سطر الأوامر (أو عبر launch(args)) تكون متاحة داخل init() وstart() عبر getParameters(). هذه هي الآلية المدمجة في JavaFX لقراءة إعدادات وقت التشغيل دون اللجوء إلى System.getenv() أو حقل ساكن.
الإغلاق النظيف
يخرج JavaFX تلقائيًا عند إغلاق آخر نافذة، لكن لديك تحكم دقيق:
Platform.setImplicitExit(false)— يمنع الخروج التلقائي عند إغلاق آخر نافذة. مفيد لتطبيقات شريط النظام التي تُخفي نافذتها دون الإنهاء.Platform.exit()— يطلب إيقاف تشغيل منظّم. يُشغّلstop()ثم يُنهي خيط تطبيق JavaFX. استدعه من أي خيط.- استدعاء
System.exit()يتجاوزstop()كليًا — تجنّبه إلا في حالات خطأ لا يمكن التعافي منها.
System.exit() أبدًا كمسار إنهاء عادي. فهو يتجاوز stop()، لذا سيُتخطّى بصمت أي كود تنظيف وضعته هناك — تفريغ الكتابات، وتحرير الأقفال، وحفظ الحالة. استخدم دائمًا Platform.exit() لإغلاق تطبيق JavaFX بشكل مناسب.
دورة الحياة عمليًا — قالب واقعي
التطبيقات الحقيقية تتجاوز الخطافات الثلاثة لدورة الحياة. إليك قالبًا يمكنك نسخه وتكييفه:
شغّل هذا وراقب وحدة التحكم — ستشاهد بالضبط أي خيط يُنفّذ كل أسلوب، مما يؤكد تسلسل دورة الحياة الذي تعلّمته أعلاه.
الخلاصة
فئة Application هي نقطة دخول ومالكة عمر كل برنامج JavaFX. يتولّى init() الإعداد السابق للواجهة على خيط المشغّل؛ ويبني start() الواجهة ويعرضها على خيط التطبيق؛ ويُحرّر stop() الموارد عند إغلاق التطبيق. يُنسّق Application.launch() كل هذا من أسلوب main(). إن وضع العمل المكثّف في init()، وعمل الواجهة في start()، والتنظيف في stop() يمنحك بنية تطبيق نظيفة ومتوقّعة منذ اليوم الأول. في الدرس القادم ستستكشف كائني Stage وScene اللذين يتلقّاهما start() ويُنشئهما.