إدارة التخطيطات المتعددة في Java Swing باستخدام CardLayout و GridBagLayout


 

في هذا المقال، سنتناول كيفية تنظيم محتوى إطار (JFrame) باستخدام عدة مديري تخطيط (Layout Managers) في Java Swing. سنقوم بتصميم واجهة مستخدم تسمح بالتنقل بين لوحات (JPanel) مختلفة ضمن جزء واحد من الإطار باستخدام CardLayout. ستوفر الأزرار التالية وظائف التحكم:

  • الزر Next: لعرض اللوحة التالية.
  • الزر Previous: لعرض اللوحة السابقة.
  • الزر First: لعرض اللوحة الأولى التي تمت إضافتها.
  • الزر Last: لعرض اللوحة الأخيرة التي تمت إضافتها.

سيتم تقسيم الإطار الرئيسي إلى قسمين، أحدهما للأزرار (اللوحة اليسرى) والآخر لعرض اللوحات المتغيرة (اللوحة اليمنى)، كما هو موضح في الصورة التوضيحية التالية:

مثال: تطبيق Main.java

يوضح الكود التالي كيفية إعداد الإطار الرئيسي، وتطبيق مديري التخطيط GridBagLayout و CardLayout، بالإضافة إلى إضافة الأزرار واللوحات التفاعلية:

import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {
    public static void main (String[] args) {
        // إنشاء إطار النافذة الرئيسي وتعيين عنوانه وحجمه
        JFrame frame = new JFrame ( "CardLayout demo" );
        frame.setSize( 400 , 200 );
        // تعيين عملية الإغلاق لإنهاء التطبيق عند إغلاق النافذة
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // استخدام GridBagLayout لترتيب المكونات داخل الإطار
        frame.setLayout( new GridBagLayout ());

        // تعريف لوحتين: panel_L للتحكم (الأزرار) و panel_R للمحتوى المتغير
        JPanel panel_L = new JPanel ();
        JPanel panel_R = new JPanel ();

        // إعداد GridBagConstraints لتحديد كيفية وضع اللوحات
        GridBagConstraints gbc = new GridBagConstraints ();
        // جعل المكونات تملأ المساحة المتاحة أفقياً وعمودياً
        gbc.fill = GridBagConstraints.BOTH;
        // تعيين وزن الجذب الأفقي والعمودي لضمان التناسب
        gbc.weightx = 1 ;
        gbc.weighty = 1 ;

        // إضافة panel_L إلى الإطار (الجانب الأيسر)
        frame.add(panel_L, gbc);

        // زيادة وزن الجذب الأفقي لـ panel_R لجعلها تأخذ مساحة أكبر (الجانب الأيمن)
        gbc.weightx = 10 ;
        frame.add(panel_R, gbc);

        // تقسيم panel_L إلى 4 صفوف وعمود واحد باستخدام GridLayout
        panel_L.setLayout( new GridLayout ( 4 , 1 ));

        // إنشاء أزرار التحكم
        JButton next = new JButton ( "Next" );
        JButton previous = new JButton ( "Previous" );
        JButton first = new JButton ( "First" );
        JButton last = new JButton ( "Last" );

        // إضافة الأزرار إلى panel_L
        panel_L.add(next);
        panel_L.add(previous);
        panel_L.add(first);
        panel_L.add(last);

        // إعداد CardLayout لـ panel_R للسماح بالتبديل بين اللوحات
        CardLayout card = new CardLayout ();
        Container container = panel_R;
        container.setLayout(card);

        // تعريف أربع لوحات محتوى مختلفة
        JPanel p1 = new JPanel ();
        JPanel p2 = new JPanel ();
        JPanel p3 = new JPanel ();
        JPanel p4 = new JPanel ();

        // تعيين ألوان خلفية مختلفة لكل لوحة للتمييز
        p1.setBackground(Color.white);
        p2.setBackground(Color.yellow);
        p3.setBackground(Color.cyan);
        p4.setBackground(Color.green);

        // إضافة تسمية (JLabel) لكل لوحة
        p1.add( new JLabel ( "Panel 1" ));
        p2.add( new JLabel ( "Panel 2" ));
        p3.add( new JLabel ( "Panel 3" ));
        p4.add( new JLabel ( "Panel 4" ));

        // إضافة اللوحات الأربعة إلى panel_R
        panel_R.add(p1);
        panel_R.add(p2);
        panel_R.add(p3);
        panel_R.add(p4);

        // إضافة مستمعي الأحداث (ActionListeners) للأزرار
        // عند النقر على Next، يتم عرض اللوحة التالية
        next.addActionListener( new ActionListener () {
            @Override
            public void actionPerformed (ActionEvent e) {
                card.next(container);
            }
        });

        // عند النقر على Previous، يتم عرض اللوحة السابقة
        previous.addActionListener( new ActionListener () {
            @Override
            public void actionPerformed (ActionEvent e) {
                card.previous(container);
            }
        });

        // عند النقر على First، يتم عرض اللوحة الأولى
        first.addActionListener( new ActionListener () {
            @Override
            public void actionPerformed (ActionEvent e) {
                card.first(container);
            }
        });

        // عند النقر على Last، يتم عرض اللوحة الأخيرة
        last.addActionListener( new ActionListener () {
            @Override
            public void actionPerformed (ActionEvent e) {
                card.last(container);
            }
        });

        // جعل النافذة مرئية
        frame.setVisible( true );
    }
}

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