أجزاء التخطيط: HBox و VBox
أجزاء التخطيط: HBox و VBox
كل تطبيق JavaFX يتجاوز نافذةً بسيطة تحتوي على زر واحد يحتاج إلى ترتيب عقد متعددة على الشاشة بطريقة منتظمة. يحل JavaFX هذه المشكلة من خلال أجزاء التخطيط (Layout Panes) — حاويات تقيس أبناءها وتضعهم تلقائيًا وفق خوارزمية ثابتة. أبسط جزئين وأكثرهما استخدامًا هما HBox الذي يرتّب العقد أفقيًا، وVBox الذي يكدّسها رأسيًا. إتقان هاذين الجزءين سيُمكّنك من تنفيذ الغالبية العظمى من تخطيطات النماذج وأشرطة الأدوات والأجزاء الجانبية في التطبيقات الحقيقية.
لماذا لا تستخدم المواضع المطلقة؟
يوفّر JavaFX فعلًا AnchorPane وPane الخام حيث يمكنك ضبط layoutX/layoutY يدويًا. تجنّب هذا الأسلوب في العمل العام على واجهات المستخدم. الإحداثيات المُدمجة في الكود تنكسر فور قيام المستخدم بتغيير حجم النافذة، أو تغيير حجم خط النظام، أو تبديل اللغة (النصوص العربية أعرض). أجزاء التخطيط تُعيد حساب المواضع عند كل تغيير في الحجم تلقائيًا — هذا هو هدفها الأساسي.
HBox: تخطيط الصف الأفقي
يضع HBox أبناءه واحدًا تلو الآخر من اليسار إلى اليمين. يحصل كل ابن على عرضه المفضّل؛ ويكبر الـHBox ليناسبهم. يمكنك التحكم في الفجوة بين الأبناء وكيفية محاذاتهم داخل الصف.
ثلاثة أمور ملحوظة هنا:
- المُنشئ الذي يقبل عناصر متغيرة
new HBox(spacing, child1, child2, ...)هو الأسلوب الأكثر إيجازًا لبناء صف — دون الحاجة إلى استدعاءgetChildren().addAll(...)منفصل. setAlignment(Pos.CENTER_LEFT)يتحكّم في موضع صف الأبناء داخل الـHBox عندما يتوفر ارتفاع زائد.setPadding(new Insets(top, right, bottom, left))يُضيف مساحة داخلية.new Insets(12)يطبّق نفس القيمة على الجوانب الأربعة.
جعل ابن يتوسع ليملأ المساحة المتبقية
حقل TextField في المثال أعلاه يستخدم عرضه المفضل فقط. في شريط بحث حقيقي أو صف نموذج تريد منه أن يتوسع ليملأ المساحة المتبقية بعد أن تأخذ التسمية والزر حصتيهما. استخدم المساعد الثابت HBox.setHgrow(node, Priority.ALWAYS):
هذا يُخبر محرك التخطيط: "امنح أي مساحة أفقية إضافية لـnameField." إذا طلب أبناء متعددون Priority.ALWAYS فإنهم يتقاسمون المساحة الزائدة بالتساوي.
ALWAYS — احصل على المساحة الزائدة عند توفرها دائمًا. SOMETIMES — استخدم المساحة الزائدة فقط إذا لم يكن ثمة ابن ALWAYS. NEVER (الافتراضي) — ابقَ بالحجم المفضّل.
VBox: تخطيط المكدّس الرأسي
VBox هو النظير الرأسي لـHBox. يُكدّس الأبناء من أعلى إلى أسفل. الواجهة البرمجية متطابقة — التباعد والمحاذاة والمسافة الداخلية وأولويات التوسع — إلا أن المحور رأسي وقيد التوسع هو VBox.setVgrow(node, Priority).
ضبط loginBtn.setMaxWidth(Double.MAX_VALUE) أسلوب شائع: يُزيل قيد الحد الأقصى لعرض الزر حتى يتمكن الـVBox من تمديده ليطابق عرضه الخاص، مما يُعطي مظهر "الزر بعرض كامل" المعتاد في شاشات تسجيل الدخول.
تداخل HBox داخل VBox (والعكس)
التخطيطات الحقيقية نادرًا ما تكون صفًا أو عمودًا واحدًا. النمط الذي ستستخدمه باستمرار هو تركيب الأجزاء: VBox كحاوية خارجية يحتوي أبناؤها على صفوف HBox واحد أو أكثر.
minWidth ثابتًا. عندما تستخدم صفوف نموذج متعددة نفس عرض التسمية، تتوافق حقول الإدخال في عمود أنيق، تمامًا كما في النماذج الاحترافية. بدون ذلك، تتحوّل المحاذاة من صف لآخر بحسب طول نص كل تسمية.
التباعد مقابل المسافة الداخلية مقابل الهامش
ثلاث آليات تباعد مختلفة متاحة في HBox/VBox ومن المفيد معرفة ما تفعله بالضبط:
- التباعد (Spacing) — الفجوة بين الأبناء، تُضبط على الجزء (
setSpacing()أو معامل المُنشئ). - المسافة الداخلية (Padding) — المسافة بين حدود الجزء وأبنائه، تُضبط على الجزء (
setPadding(new Insets(...))). - الهامش (Margin) — مساحة إضافية حول ابن معين، تُضبط لكل عقدة على حدة (
HBox.setMargin(node, new Insets(...))أوVBox.setMargin(node, new Insets(...))).
في معظم النماذج يكفي التباعد والمسافة الداخلية. استخدم الهوامش لكل عقدة عندما تحتاج ابنًا واحدًا إلى إبعاده عن إخوته دون التأثير على التباعد العام للصف.
تنسيق HBox و VBox بـCSS
يقبل الجزءان CSS عبر طريقة setStyle() أو عبر ورقة أنماط. أكثر الخصائص فائدة هي -fx-background-color و-fx-background-radius و-fx-border-color و-fx-padding (التي تعادل setPadding()). يُفضّل استخدام أوراق الأنماط الخارجية على استدعاءات setStyle() المُدمجة للحفاظ على الفصل بين منطق الواجهة والتنسيق.
setStyle(). ضبط -fx-padding في ورقة الأنماط وفي setPadding() في الكود في آنٍ واحد يجعل أحدهما يُلغي الآخر بصمت. اختر أسلوبًا واحدًا والتزم به في كامل التطبيق.
الخلاصة
HBox وVBox هما جزءا التخطيط الأساسيان في JavaFX. استخدم HBox لبناء أشرطة الأدوات وصفوف الأزرار وحقول النموذج المُعنونة جنبًا إلى جنب. استخدم VBox لتكديس الأقسام واللوحات وصفوف النموذج من أعلى إلى أسفل. اجمعهما بتداخل أحدهما داخل الآخر، وتحكّم في المساحة البيضاء بالتباعد والمسافة الداخلية والهامش، وادفع سلوك التوسع بـHBox.setHgrow / VBox.setVgrow. في الدرس التالي ستتعرّف على BorderPane وGridPane — الأجزاء المناسبة لتخطيطات النوافذ متعددة المناطق والشبكات الجدولية الدقيقة.