Jesteś gotowy(-a) na wariant układu w "Swing", który daje najwięcej elastyczności (i z tego powodu jest najtrudniejszy w obsłudze 🧠) 🙂? Teraz czas na układ "GridBagLayout", czyli tworzenie nieregularnych siatek komponentów w "Swing"! Ostrzegam - jest o wiele bardziej skomplikowany, niż poprzednik o podobnej nazwie ⚠️.

"GRIDBAGLAYOUT" W "SWING" JAKO NAJBARDZIEJ ZAAWANSOWANY UKŁAD ZE WSZYSTKICH!

"GridBagLayout" również układa komponenty w formie siatki, natomiast tutaj mamy większe pole do popisu 😲. Poprzez ustawianie wartości wielu właściwościom, możemy swobodnie regulować kształt i pozycję każdego z komponentów, dzięki czemu uzyskujemy dostęp do tworzenia przeróżnych kształtów 🔥. Stąd też, trzeba podejść zupełnie inaczej do samego etapu wprowadzania ich do układu ⚠️!

Celem regulowania pozycji i rozmiaru danego komponentu, potrzebujemy dodatkowego obiektu pozwalającego na konfigurację poszczególnych wartości ℹ️. Jest nim instancja klasy o nazwie "GridBagConstraints". Jest to taki "worek konfiguracyjny" umożliwiający dostosowywanie wszystkich pól dotyczących układu "GridBagLayout" 🔧. Dzięki niemu możesz ustawić np. szerokość jednej kratki w jednostkach pól, czyli możemy w ten sposób sprawić, żeby jedna kratka zajmowała 2 pola szerokości i 3 wysokości 💡. 

PRZYKŁAD KODU ŹRÓDŁOWEGO

Jak zwykle, kod źródłowy w charakterze przykładu. Tym razem odseparowałem ramkę ("JFrame") od panelu ("JPanel"), aby wszystkie kwestie związane z "GridBagLayout" były w jednym miejscu 👍. Lećmy z koksem 💪!

KLASA "MAIN"
public class Main {
	public static void main(String[] args) {
		SwingUtilities.invokeLater(MainJFrame::new);
	}
}

Klasa z metodą uruchomieniową - taka sama bez zmian 😁!

KLASA "MAINJFRAME"
import java.awt.*;
import javax.swing.*;

public class MainJFrame extends JFrame {
	private final GridBagLayoutJPanel gridBagLayoutJPanel = new GridBagLayoutJPanel();

	public MainJFrame() {
		configureFrame();
		addPanelToFrame();
	}

	private void configureFrame() {
		setTitle("Układ GridBagLayout w Swing");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		setResizable(false);
		setSize(352, 256);
		setLocationRelativeTo(null);
	}

	private void addPanelToFrame() {
		getContentPane().add(BorderLayout.CENTER, gridBagLayoutJPanel);
	}
}

Tu mamy naszą "ramkę", która zawierać będzie wbudowany panel dla "GridBagLayout". U góry mamy tworzenie obiektu, a że potem nic nie będzie nadpisywane, możemy zastosować modyfikator "final". I tak robimy 😉!

W drugiej metodzie dodajemy wspomniany panel postępując zgodnie z układem "BorderLayout". Panel znajdzie się w centralnym regionie układu ℹ️.

KLASA "GRIDBAGLAYOUTJPANEL"
import java.awt.*;
import javax.swing.*;

public class GridBagLayoutJPanel extends JPanel {
	private final JLabel labelA = new JLabel("Tekst A");
	private final JLabel labelB = new JLabel("Tekst B");
	private final JButton buttonA = new JButton("Przycisk A");
	private final JButton buttonB = new JButton("Przycisk B");
	private final JButton buttonC = new JButton("Przycisk C");

	public GridBagLayoutJPanel() {
		super(new GridBagLayout());
		addComponentsToPanel();
	}

	private void addComponentsToPanel() {
		var gridBagConstraints = new GridBagConstraints();

		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 0;
		gridBagConstraints.ipadx = 8;
		gridBagConstraints.ipady = 8;

		add(labelA, gridBagConstraints);

		gridBagConstraints.gridx = 2;
		gridBagConstraints.ipady = 32;
		gridBagConstraints.gridheight = 2;

		add(buttonA, gridBagConstraints);

		gridBagConstraints.gridx = 1;
		gridBagConstraints.gridy = 1;
		gridBagConstraints.gridwidth = 1;
		gridBagConstraints.gridheight = 2;
		gridBagConstraints.anchor = GridBagConstraints.WEST;
		gridBagConstraints.ipady = 96;

		add(buttonB, gridBagConstraints);

		gridBagConstraints.gridwidth = 2;
		gridBagConstraints.gridheight = 1;
		gridBagConstraints.gridx = 0;
		gridBagConstraints.gridy = 3;
		gridBagConstraints.ipadx = 0;
		gridBagConstraints.ipady = 0;
		gridBagConstraints.fill = GridBagConstraints.BOTH;

		add(buttonC, gridBagConstraints);

		gridBagConstraints.gridx = 2;
		gridBagConstraints.gridwidth = 1;

		add(labelB, gridBagConstraints);
	}
}

Teraz panel. Jak widzisz, poza tworzeniem komponentów u samej góry, mamy 2 kolejne kluczowe miejsca w kodzie ‼️.

Po pierwsze, ustawianie układu w konstruktorze 1️⃣. Poprzez użycie słowa "super", możesz uniknąć wywołania metody "setLayout" 😉! "JPanel" dopuszcza możliwość ustawienia układu w miejscu odwoływania się do konstruktora klasy bazowej ℹ️.

Po drugie, metoda dodająca komponenty 2️⃣. Jak łatwo zauważyć, jest o wiele więcej instrukcji niż w całej reszcie ukazanych przykładów 😅. "GridBagLayout" w "Swing" pozwala na swobodne dostosowywanie układu siatki dla komponentów. Aczkolwiek, w przeciwieństwie do "GridLayout"może znacznie odbiegać od widoku siatkowego i przyjmować niestandardowe kształty ❤️.

Tradycyjnie, korzystamy z metody "add", lecz tym razem wprowadzamy do niej 2 parametry 👇:

  1. komponent jaki ma zostać dodany,
  2. obiekt z konfiguracją poszczególnych wartości.

Zauważ, że tak jak pisałem, jest zgoła odmienny proces dodawania komponentów ⚠️. Najpierw ustawiamy wartości, potem dodajemy komponent. Ustawianie, dodawanie. I tak cały czas ✅. Innymi słowy, konfigurujemy odpowiednie pola dla kolejnego komponentu, który chcemy dodać do "GridBagLayout" w "Swing".

Wywołując metodę "add" i dodając obiekt "GridBagConstraints" jako drugi parametr, układ sugeruje się aktualnymi wartościami pól, które zostały nadane tuż przed tą metodą. Jeszcze inaczej można napisać, że każdy komponent konfigurujemy osobno, czyli na bieżąco odpowiednio dostosowujemy "zestaw" wartości przed wstawieniem kolejnego komponentu.

Na koniec, mała wzmianka o słowie kluczowym "var", które znajduje się w miejscu tworzenia obiektu "GridBagConstraints" - możesz dzięki niemu uchylić się od podawania typu zmiennej lokalnej 👑!

Teraz czas na wyjaśnienie samych ustawień, jakie znajdują się pomiędzy wywołaniami "add".

PARAMETRY OBIEKTU "GRIDBAGCONSTRAINTS"

"GridBagConstraints" posiada naprawdę sporo parametrów jakie możesz swobodnie regulować 🔧. Ja, w podanym przykładzie skorzystałem z następujących (i wyjaśnię tylko te) 👇:

  1. "gridx" (pozycja komponentu w jednostkach "kratkowych" w osi X),
  2. "gridy" (pozycja komponentu w jednostkach "kratkowych" w osi Y),
  3. "gridwidth" (szerokość komponentu w jednostkach "kratkowych" - "GridBagLayout" w "Swing" pozwala na nieregularne wielkości komponentów działające w stylu "rowspan" i "colspan" dla tabelek w języku HTML),
  4. "gridheight" (wysokość komponentu w jednostkach "kratkowych"),
  5. "ipadx" (margines wewnętrzny komponentu w osi X),
  6. "ipady" (margines wewnętrzny komponentu w osi Y),
  7. "fill" (rodzaj "wypełniania" wolnej przestrzeni przez komponent - jako wartość, wprowadzamy wbudowane wartości typu wyliczeniowego),
  8. "anchor" (rodzaj "zakotwiczenia" komponentu - pozwala to na ustalenie czy komponent przyjmujący mniejsze rozmiary od wolnej przestrzeni ma się "trzymać" lewej strony, prawej strony lub środka; tutaj również korzystamy z typu wyliczeniowego).

Pełna gama parametrów (jak również szczegóły związane z typami wyliczeniowymi) dostępna jak zwykle w dokumentacji Oracle 📖.

PRZECZYTAJ TO!

Musisz mieć świadomość, że podawane wartości dla poszczególnych pól nie są zawsze "honorowane" ⛔. Muszą być zachowywane jakieś restrykcje i priorytety przez co raz otrzymujemy pożądany efekt bez problemów, a czasami nie 😞.

Tak czy siak, odpalenie aplikacji z powyższym kodem źródłowym przyniesie tam taki efekt 👇:

Wygląd przycisków w panelu "JPanel" z układem "GridBagLayout" w "Swing"

"GridBagLayout" w "Swing" otwiera drogę programistom do tworzenia bardzo nieregularnych układów komponentów, które nie mogą zostać zrealizowane przy użyciu wszystkich poprzednich układów.

Takiego rozstawienia elementów nie da Ci żaden inny układ o dużo prostszej konfiguracji 😅!


Tyle w temacie 😄! Zważywszy, że układ lubi wystawiać naszą cierpliwość na próbę jeśli chodzi o konfigurację 🙂, zalecam go stosować tylko, gdy naprawdę nie możemy osiągnąć zamierzonego efektu przy pomocy wcześniej poznanych układów. On potrafi dać mocno w skórę 💪! Jak to tylko możliwe, korzystaj z uprzednio skonfigurowanych układów tak często, jak to możliwe 👍.

PODOBNE ARTYKUŁY