Czas przedstawić Tobie kolejny układ jaki występuje w bibliotece "Swing" - mianowicie, "FlowLayout" 🔥! Dowiesz się nie tylko tego, w jaki sposób ustawić ten układ, lecz także jak on wpływa na wygląd komponentów, gdy umieścimy je w ramce albo w panelu ⚡! Wchodź, zapraszam 😊!

"FLOWLAYOUT" W "SWING" KOLEJNYM RODZAJEM UKŁADU KOMPONENTÓW

W jednym z poprzednich artykułów przytoczyłem układ komponentu, który jest domyślnym dla obiektów "JFrame" - "BorderLayout" 💡. "FlowLayout" jest z kolei domyślnym dla paneli (obiektów "JPanel") 🔥!

OPIS UKŁADU "FLOWLAYOUT"

"FlowLayout" działa on w taki sposób, że "naciąga się" (poszerza swoje rozmiary) dostosowując swój rozmiar do umieszczonych w nim komponentów ℹ️. Warto nadmienić, że to "dostosowywanie się" działa inaczej w przypadku, gdy wspomniany układ funkcjonuje dla ramki ("JFrame") bądź dla komponentu osadzonego w jednym z regionów "BorderLayout". Jak się przekonasz na zamieszczonych przykładach, nic nie stoi na przeszkodzie, aby za pomocą metody "setLayout", ustawić go w "JFrame" i w "JPanel" 🙂.

PRZYKŁAD KODU ŹRÓDŁOWEGO

Przedstawię 2 różne kody źródłowe prezentujące działanie tego układu zarówno w ramce ("JFrame"), jak i w panelu ("JPanel") ✅. Dodamy sobie kilka tekstów (komponentów "JLabel") celem zbadania jak będą reagować w obu przypadkach 😉.

"FLOWLAYOUT" USTAWIONE W "JFRAME"

Zacznijmy od programu, w którym wprowadzamy "FlowLayout" do "JFrame" 🔲.

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

Standardowo zaczynamy od metody "main". Nic się nie zmienia w kontekście przykładów ukazywanych poprzednio.

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

public class MainJFrame extends JFrame {
	private final JLabel labelA = new JLabel("Pierwszy tekst w układzie \"FlowLayout\"");
	private final JLabel labelB = new JLabel("Drugi tekst w układzie \"FlowLayout\"");
	private final JLabel labelC = new JLabel("Trzeci nieco większy tekst w układzie \"FlowLayout\"");
	private final JLabel labelD = new JLabel("Czwarty tekst w układzie \"FlowLayout\"");

	public MainJFrame() {
		configureFrame();
		setLineBordersToLabels();
		addToFrame();
	}

	private void configureFrame() {
		setTitle("Układ FlowLayout w Swing (JFrame)");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLayout(new FlowLayout());
		setVisible(true);
		setResizable(false);
		setSize(512, 128);
		setLocationRelativeTo(null);
	}

	private void setLineBordersToLabels() {
		var lineBorder = new LineBorder(Color.BLACK);

		labelA.setBorder(lineBorder);
		labelB.setBorder(lineBorder);
		labelC.setBorder(lineBorder);
		labelD.setBorder(lineBorder);
	}

	private void addToFrame() {
		add(labelA);
		add(labelB);
		add(labelC);
		add(labelD);
	}
}

W klasie potomnej "JFrame" mamy całość kodu odpowiedzialnego za utworzenie okna z zawartością. Prywatne składowe finalne dotyczą naszych tekstów (finalne dlatego, gdyż nie będą tworzone nowe obiekty przez cały cykl działania). W metodzie "configureFrame", poza wcześniej wyjaśnianymi metodami, mamy jedną, na którą musimy zwrócić szczególną uwagę 🚨.

"setLayout" zamienia domyślny układ (w tym wypadku "BorderLayout") na dowolny inny 👍. Za parametr przyjmuje typ "LayoutManager", czyli tak naprawdę to "menedżer układu", jednak biorąc pod uwagę nazwy "BorderLayout" i "FlowLayout" w "Swing" od razu wnioskujemy, że chodzi o sam "układ" (ech, ta Java 😜...). Przeważnie wstawia się konstruktor istniejącego układu i to zwykle wystarcza ✔️.

Ważne, aby wspomnieć o tym, że w przypadku zmiany układu na "FlowLayout", zapominamy kompletnie o metodzie "getContentPane" ⚠️! Ona nie dotyczy układu "FlowLayout". Tu wywołujemy od razu metodę "add" i wprowadzamy tylko jeden parametr, jakim jest komponent, który chcemy tam wstawić 🙂.

Po uruchomieniu programu, ujrzysz 4 teksty ustawione blisko siebie, a każde z nich ma na sobie prostą czarną ramkę. Za to odpowiada "setBorder", do którego dodajemy obiekt typu "LineBorder" (który wymaga zaimportowania pakietu "javax .swing.border.LineBorder" 📪). Wstawiłem ją celowo, aby pokazać Ci jedną istotną cechę tego układu 😲.

Jeżeli skrócisz jeden z tekstów i ponownie uruchomisz program, to ułożenie tychże tekstów ulegnie zmianie 😳. W jednym rzędzie wstawi się tyle elementów, na ile pozwoli maksymalna szerokość ramki, na którą nałożono układ "FlowLayout". Wniosek z tego nasuwa się taki, iż "FlowLayout" stara się domyślnie umieścić wszystko w jednym rzędzie, zachowując tylko tyle miejsca, ile trzeba, a jeżeli kolejny element już nie mieści się w tym samym rzędzie, to zostaje on umieszczony poniżej ⏬. Czyli w odróżnieniu od "BorderLayout", ten układ dostosowuje szerokość komponentów względnie do zawartości w środku. Dotyczy to wszystkich komponentów.

Wygląd tekstów w ramce "JFrame" z układem "FlowLayout" w "Swing"

Wygląd tekstów w komponencie "JFrame" przy użyciu układu "FlowLayout" w "Swing".

Mogłeś(-aś) dostrzec słowo kluczowe "var" - ono pozwala uniknąć definiowania typu zmiennej samodzielnie, "przerzucając" ten obowiązek na kompilator. Polecam z tego korzystać jak najczęściej, a kiedy można tego użyć, to zapraszam do odrębnego artykułu 😊.

"FLOWLAYOUT" W "SWING" W OBIEKCIE "JPANEL"

Teraz przypadek, gdy "FlowLayout" w "Swing" dotyczy panelu osadzonego w ramce "JFrame", w której dalej obowiązuje "BorderLayout" 🚨! Jeżeli "FlowLayout" dotyczy obiektu "JPanel", to spodziewaj się innej reakcji, gdy suma szerokości wszystkich komponentów w jednym rzędzie zostanie przekroczona 😱. Aby zaobserwować to zjawisko, będziemy potrzebować dodatkowej klasy dla panelu w środku którego, znajdą się nasze komponenty tekstowe ✒️.

KLASA "MAIN"

Klasa uruchomieniowa jest taka sama. Weź ją sobie z góry, co będę się powtarzał 😄!

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

public class MainJFrame extends JFrame {
	private final FlowLayoutJPanel flowLayoutJPanel = new FlowLayoutJPanel();

	public MainJFrame() {
		configureFrame();
		getContentPane().add(BorderLayout.EAST, flowLayoutJPanel);
	}

	private void configureFrame() {
		setTitle("Układ FlowLayout w Swing (JPanel)");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		setResizable(false);
		setSize(512, 128);
		setLocationRelativeTo(null);
	}
}

Tutaj już mamy różnice 😉. Kod jest dużo mniejszy z powodu przeniesienia komponentów tekstowych do panelu ("FlowLayoutJPanel") 😁. Zwróć uwagę, że teraz dodajemy do ramki sam panel i, co ważne, korzystamy ze stylu zapisu dostosowanego dla "BorderLayout" - "getContentPane" i wartość typu wyliczeniowego ("BorderLayout.EAST") 💡.

KLASA "FLOWLAYOUTJPANEL"
import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;

public class FlowLayoutJPanel extends JPanel {
	private final JLabel labelA = new JLabel("Pierwszy tekst w układzie \"FlowLayout\"");
	private final JLabel labelB = new JLabel("Drugi tekst w układzie \"FlowLayout\"");
	private final JLabel labelC = new JLabel("Trzeci nieco większy tekst w układzie \"FlowLayout\"");

	public FlowLayoutJPanel() {
		super(new FlowLayout());
		setLineBordersToLabels();
		addToPanel();
	}

	private void setLineBordersToLabels() {
		var lineBorder = new LineBorder(Color.BLACK);

		labelA.setBorder(lineBorder);
		labelB.setBorder(lineBorder);
		labelC.setBorder(lineBorder);
	}

	private void addToPanel() {
		add(labelA);
		add(labelB);
		add(labelC);
	}
}

Tym razem tworzymy sobie trzy teksty, zamiast czterech. Obiekty są tak samo umieszczone u góry klasy. W konstruktorze jest ciekawy zapis 🌟. "super" w języku Java to "zwrócenie się" do konstruktora klasy bazowej (więcej informacji w osobnym materiale). O wiele istotniejsze jest to, że dzięki takiej sztuczce unikamy wywoływania "setLayout"! Reszta metod odpowiada za nałożenie tego samego obramowania do tekstów i dodanie ich do panelu.

Gdy skompilujesz sobie program, ujrzysz całkiem inny efekt. W oknie będą widoczne...dwa teksty. Tak - dwa, nie trzy 🤯! Co więcej, w momencie przekroczenia szerokości panelu, nie dojdzie do umieszczenia tekstu poniżej 😳! W przypadku, gdy komponenty wstawione do panelu nie mieszczą się w jednej linii, dochodzi do wyjścia komponentów poza wymiary okna ⚠️!

Ciekawostka kryje się także przy "pustym" układzie 🔔. Jeżeli komponent z układem "FlowLayout" w "Swing" jest pusty (nie ma w sobie żadnych komponentów), wtedy zostaje sama "listwa" panelu. Komponent będzie widoczny, lecz zajmie bardzo niewielką powierzchnię na ekranie. Najlepiej ustawić sobie tło panelu używając metody "setBackground", zaraz po instrukcji "super" 👇:

setBackground(Color.BLACK);

Wtedy zobaczysz o co mi chodzi ☑️.

Wygląd tekstów w ramce "JPanel" z układem "FlowLayout" w "Swing"

Wygląd tekstów w komponencie "JPanel" przy użyciu układu "FlowLayout" w "Swing".


To wszystko na temat nowo poznanego układu. Być może są jeszcze jakieś różnice których nie zawarłem, jednak nie ma sensu odkrywać wszystkich zakątków takiego zagadnienia, jak na artykuł wrzucony do sieci 🌐. To ma być przyjemne wprowadzenie 😁!

NASTĘPNY ARTYKUŁ: BoxLayout w Swing. Prostokątny układ komponentów

PODOBNE ARTYKUŁY