Java - Swing Layouts


Raspoređivanje komponenti unutar nekog kontejnera izvršava se prema predefinisanom „formatu“. Ovaj format se naziva Layout, odnosno izgled kontejnera. Unutar Swinga i AWT-a postoje predefinisani tipovi izgleda (LayoutManager-i) koje možemo koristiti. Layout je način na koji će se kontrole raposređivati unutar kontejnera. Za tu svrhu postoje posebne klase, koje se nazivaju LayoutManager-i, i koje implementuju interfejs LayoutManager. Java AWT layouti su:

  • BorderLayout,
  • FlowLayout,
  • CardLayout,
  • GridLayout,
  • GridBagLayout.

Java Swing Layout-i su:

  • BoxLayout,
  • GroupLayout,
  • SpringLayout.


GroupLayout

GroupLayout je podrazumjevani LayoutManager NetBeans dizajnera (GUI Builder). To znači da kada JFrame dodamo u naš projekat, on podrazumjevano ima GroupLayout. Ovaj izgled podrazumeva prozor podjeljen na grupe i nije baš tako jednostavan za ručno korišćenje iako ga okruženje koristi. GroupLayout podrazumjeva dva pravca (horizontalni i vertikalni) i dva tipa postavljanja kontrola (sekvencijalno i paralelno). Pogledajmo sljedeći kod kako bi vam ovo bilo jasnije.

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

public class Main {

    public static void main(String[] args) {
        JFrame frame = new JFrame(); // Kreiranje forme
        
        GroupLayout layout = new GroupLayout(frame.getContentPane());
        frame.setLayout(layout);
        
        JButton button1 = new JButton("Dugme broj 1"); // Prvo dugme
        JButton button2 = new JButton("Dugme broj 2"); // Drugo dugme
        JButton button3 = new JButton("Dugme broj 3"); // Drugo dugme
        JButton button4 = new JButton("Dugme broj 4"); // Drugo dugme
        
        layout.setAutoCreateGaps(true); // Linije za odredjivanje automatskog razmaka
        layout.setAutoCreateContainerGaps(true);
        
        layout.setHorizontalGroup(layout.createSequentialGroup().addComponent(button1).addComponent(button2).addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(button3).addComponent(button4)));
        layout.setVerticalGroup(layout.createSequentialGroup().addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(button1).addComponent(button2).addComponent(button3).addComponent(button4)));
        
        frame.setSize(600, 400);
        frame.setLocationRelativeTo(null); 
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

Prikaz koda iz gornjeg primjera izgledaće ovako:




BoxLayout

BoxLayout ređa kontrole jednu nakon druge, po određenoj osi. Pogledajmo sljedeći kod kako bi vam ovo bilo jasnije.

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

public class Main {

    public static void main(String[] args) {
        JFrame frame = new JFrame(); // Kreiranje forme
        
        frame.setLayout(new BoxLayout (frame.getContentPane(), BoxLayout.PAGE_AXIS)); // Redjanenje komponenti
        
        JButton button1 = new JButton("Dugme broj 1"); // Prvo dugme
        JButton button2 = new JButton("Dugme broj 2"); // Drugo dugme
        
        frame.add(button1); // Dodavanje provg dugmeta na formu
        frame.add(button2); // Dodavanje drugog dugmeta na formu
        
        frame.setSize(600, 400);
        frame.setLocationRelativeTo(null); 
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

Prikaz koda iz gornjeg primjera izgledaće ovako:




SpringLayout

SpringLayout omogućava postavljanje ograničavača (metodom putConstraint()) tako da se svaka kontrola smješta na određenu lokaciju poštujući pravila određenog ograničavača. U sljedećem primjeru dugme će biti pozicionirani 100 tačaka zapadno i 150 tačaka sjeverno:

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SpringLayout;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

public class Main {

    public static void main(String[] args) {
        JFrame frame = new JFrame(); // Kreiranje forme
        
        SpringLayout layout = new SpringLayout();
        frame.setLayout(layout);
        
        JButton button = new JButton("Dugme");
        
        layout.putConstraint(SpringLayout.WEST, button, 100, SpringLayout.WEST, frame); // Pozicioniranje dugmeta
        layout.putConstraint(SpringLayout.NORTH, button, 150, SpringLayout.NORTH, frame); // Pozicioniranje dugmeta
        
        frame.add(button); // Dodavanje dugmeta na formu
        
        frame.setSize(600, 400);
        frame.setLocationRelativeTo(null); 
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

Prikaz koda iz gornjeg primjera izgledaće ovako:




Ovakav pristup omogućava nam da pozicioniramo kontrolu na bilo koju lokaciju unutar prozora. SpringLayout predstavlja layout koji je moguće primjeniti samo programabilno, jer nije podržan u okviru NetBeans razvojnog okruženja. GroupLayout se smatra mnogo boljom alternativom.


Zadatak za vježbu

Potrebno je napraviti Java aplikaciju – slagalica. Aplikacija će se sastojati od 12 tastera raspoređenih na JFrame kontroli pomoću GridLayout-a. Jedan taster će uvijek biti nevidljiv i svaki pritisnuti taster biće premješten na mjesto nevidljivog tastera, a nevidljivi taster će zauzimati njegovu poziciju. Ukoliko se aktivirani taster ne nalazi odmah pored nevidljivog tastera, treba onemogućiti premještanje tastera.




Rješenje zadataka!

import java.awt.*;
import java.awt.event.*;
import javax.swing.JButton;

public class Main
{
    static JButton invisible;
    static void switchButtons(JButton clickedButton)
    {

    if(invisible.getLocation().x < (clickedButton.getLocation().x - 
    clickedButton.getSize().width)
    || invisible.getLocation().x >
    (clickedButton.getLocation().x + clickedButton.getSize().width)
    || invisible.getLocation().y <
    (clickedButton.getLocation().y - clickedButton.getSize().height)
    || invisible.getLocation().y >
    (clickedButton.getLocation().y + clickedButton.getSize().height)
    || (invisible.getLocation().y !=
    clickedButton.getLocation().y
    && invisible.getLocation().x !=
    clickedButton.getLocation().x))
    return;
    
        Point tmpLoc = clickedButton.getLocation();
        clickedButton.setLocation(invisible.getLocation());
        invisible.setLocation(tmpLoc);
    }
public static void main(String[] args)
{
    LayoutManager layOut = new GridLayout(3, 3);
    
    Frame f = new Frame();
    f.addWindowListener(new WindowAdapter()
    {
        
        @Override
        public void windowClosing(WindowEvent e)
        {
            System.exit(0);
        }
    });
    f.setLayout(layOut);

    JButton btn = new JButton();
    for(int i=1; i<13; i++)
    {
        btn = new JButton(String.valueOf(i));
        btn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                switchButtons((JButton) e.getSource());
            }
        });
    f.add(btn);
    }
    btn.setVisible(false);
    invisible = btn;

    f.setSize(300, 300);
    f.setVisible(true);
    }
}