W niniejszym artykule o bibliotece "Swing" języka Java, już znajdującym się w kategorii bezpośrednio związanej z tym tematem, wtajemniczę Cię w podstawowe elementy jakie możesz wstawić do okna 🪟. Aby w ogóle zrobić cokolwiek, trzeba najpierw poznać podstawowe komponenty "Swing". To będzie sama lista z krótkim opisem co do czego służy i jak prezentuje się w oknie. Jak zainteresowany(-a), to zapraszam 👋!
OTO JAKIE MOŻESZ ZNALEŹĆ KOMPONENTY W "SWING"!
Komponent, mam na myśli pojedynczy widoczny element okna, taki puzzel 🧩. W "Swing", interfejsy użytkownika budowane są poprzez tworzenie komponentów i przydzielanie im miejsca w oknie (prawie jak puzzle 🙂). Teksty, przyciski, listy rozwijane i tym podobne rzeczy, nazywane są komponentami ℹ️. Zanim jednak zaczniemy je poznawać, musimy się dowiedzieć jak je ujrzeć w oknie 😳.
JAK ZACZĄĆ?
Artykuł wprowadzający do biblioteki "Swing", w którym zaprezentowałem tworzenie samego okna, znajduje się tutaj, a w tym miejscu jedynie przypomnę jak sprawić, żeby dowolny komponent pojawił się w oknie.
W klasie odpowiedzialnej za wyświetlanie okna ("JFrame"), obiekt komponentu do okna wprowadzisz używając metody "add", dostępnej po wywołaniu innej metody, "getContentPane" 👇:
getContentPane().add([komponent]);To jest najprostsza droga do tego, aby ujrzeć dany komponent w środku okna ✅.
LISTA KOMPONENTÓW
Teraz komponenty! Przedstawię Ci zbiór takich, jakie uważam za podstawowe. Podam nazwę jaką przyjmuje w kodzie, opiszę krótko co to jest i zarzucę obrazek jak to wygląda w swojej standardowej (domyślnej) formie ✔️.
JLABEL
"Etykieta", czyli po prostu miejsce na tekst 😄. Najbardziej podstawowy konstruktor oczekuje jedynie podania łańcucha znaków. Wtedy pojawi się po lewej stronie okna ℹ️. Możesz także określić wyrównanie, czyli od której strony ma zostać wyświetlony 👍. Używamy wtedy specjalnego typu wyliczeniowego "SwingConstants", dzięki któremu ustalamy czy ma być pisany od lewej strony, na środku, czy od prawej strony.
Dla przykładu, taka postać 👇:
var label = new JLabel("Jestem tekstem!", SwingConstants.CENTER);spowoduje wypisanie podanego łańcucha na środku okna. Wtedy tak on wygląda:
Wygląd komponentu "JLabel" w bibliotece "Swing".
Gdybyś chciał(a) zmienić sobie rozmiar czcionki (bo domyślnie jest bardzo mała), to jest jeden trik polegający na wywołaniu metody "setFont" w następującej postaci:
label.setFont(new Font(label.getFont().getName(), Font.PLAIN, 32));Efekt: nałożenie tej samej czcionki, którą ma nasza "etykieta", bez pogrubiania ani kursywy, o rozmiarze 32 pikseli 🌟.
JBUTTON
"JButton" to przycisk, który możemy kliknąć, aby powstała jakaś reakcja ⏩. Celem zdefiniowania co ma się wydarzyć po kliknięciu, należy nałożyć metodę do zdarzenia kliknięcia przycisku, które pełni rolę "wywołania zwrotnego" (ang. callback) - metody wywoływanej "z opóźnieniem" pod wpływem jakiegoś zdarzenia ℹ️. Pokazuję nieco niżej jak się to robi.
TWORZENIE PRZYCISKU
Sam przycisk niewykonujący żadnych czynności, wymaga jedynie użycia konstruktora, w którym wprowadzamy łańcuch znaków, czyli jaki tekst ma przyjmować przycisk 📝. Oto prosty przykład konstruktora z łańcuchem znaków 👇:
var button = new JButton("Jestem przyciskiem!");Wówczas po dodaniu go do okna, zobaczymy przycisk w całej okazałości:
![]() |
Wygląd komponentu "JButton" w bibliotece "Swing".
Miej jednak na uwadze, iż przycisk może przybierać różne rozmiary w zależności od układu ramki/panelu, do którego się go "przykleiło" . Na przykład "BorderLayout" sprawi, że przycisk zajmie calutką powierzchnię okna wyczerpując przestrzeń co do piksela 🔥! Zaś "GridLayout" (znowu na przykład 😝), ustawi przycisk w jednej z komórek siatki.
DEFINIOWANIE ZDARZENIA PO KLIKNIĘCIU PRZYCISKU
Jak już tworzymy przycisk, to po to, żeby coś robił 😄! W celu dodania zdarzenia do przycisku "Swing", należy albo dorzucić klasę wewnętrzną i do niej zaimplementować interfejs "ActionListener", albo skorzystać z podejścia znanego z paradygmatu funkcyjnego - z wyrażenia lambda. W obu przypadkach korzystamy z metody "addActionListener" 👇:
button.addActionListener([implementacja interfejsu ActionListener]);To nam pozwala na zdefiniowanie reakcji na zdarzenie kliknięcia przycisku 💥. W miejsce parametru wprowadzamy implementację interfejsu "ActionListener". Najlepiej wstawić wyrażenie lambda osadzone bezpośrednio w miejsce parametru:
button.addActionListener(event -> System.out.println("Kliknięto przycisk!"));Powyższy zapis da mały efekt po kliknięciu przycisku: wypisanie w konsoli tekstu 🙂.
JTEXTFIELD
Pole tekstowe, do którego możemy wstawić dowolną treść przy pomocy klawiatury - to znajdziesz pod hasłem "JTextField". Podobnie jak z przyciskiem, tutaj też możemy określać co się stanie po wprowadzeniu lub usunięciu dowolnego znaku 🧨.
TWORZENIE POLA TEKSTOWEGO
Oto jeden z wariantów konstruktora, do którego wprowadzamy tekst i szerokość pola w znakach 👇:
var textField = new JTextField("Jestem polem tekstowym!");A tak prezentuje się pole tekstowe:
Wygląd komponentu "JTextField" w bibliotece "Swing".
Tutaj też szerokość pola zależy od układu, którym posługuje się ramka bądź panel. "BorderLayout" rozciągnie na całą powierzchnię, a np. "FlowLayout" wyznaczy szerokość na podstawie długości tekstu, jaki występuje w środku od chwili uruchomienia naszej aplikacji (chyba, że wstawimy drugi parametr liczbowy określający szerokość pola w znakach).
DEFINIOWANIE ZDARZENIA PO EDYCJI TREŚCI POLA TEKSTOWEGO
Aby dostać się do zdarzeń wprowadzenia lub usunięcia znaku, trzeba sięgnąć po bardziej niekonwencjonalny zapis. Najpierw wywołujemy metodę "getDocument", a potem "addDocumentListener". W miejsce parametru, definiujemy implementację interfejsu "DocumentListener", który przyjmuje 3 metody 👇:
- "insertUpdate" (zdarzenie wprowadzenia znaku),
- "removeUpdate" (zdarzenie usunięcia znaku),
- "changedUpdate" (zdarzenie zmiany stylu znaków odpalane wyłącznie w typie "StyledDocument").
Gdy chcemy dla przykładu, zaprogramować wypisywanie w konsoli aktualną liczbę znaków co dowolne wprowadzenie lub usunięcie znaku, musimy napisać tak:
textField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent documentEvent) {
writeTextLength();
}
@Override
public void removeUpdate(DocumentEvent documentEvent) {
writeTextLength();
}
@Override
public void changedUpdate(DocumentEvent documentEvent) {
writeTextLength();
}
private void writeTextLength() {
System.out.println(textField.getText().length());
}
});Stosując tę metodę, możesz wpływać na inne komponenty w "Swing" 🔥! Na przykład można sprawić, że przycisk będzie zablokowany, jeśli okaże się, że pole tekstowe jest puste 💡.
JTEXTAREA
"JTextArea" także jest polem tekstowym, jednak w odróżnieniu od poprzednika, tutaj możemy wstawić wiele wierszy tekstu do jednego pola.
TWORZENIE WIELOWIERSZOWEGO POLA TEKSTOWEGO
Konstruktor przyjmuje 3 parametry 👇:
- łańcuch znaków jaki zostanie do niego umieszczony po uruchomieniu aplikacji (obowiązkowy),
- liczba wierszy (opcjonalny),
- liczba kolumn (opcjonalny).
Dodanie tylko pierwszego z nich sprawi, że pole tekstowe zacznie się "rozciągać" zgodnie z zawartością w środku:
var textArea = new JTextArea("Jestem polem tekstowym...\n...składającym się z wielu wierszy!");W oknie wygląda to następująco:
![]() |
Wygląd komponentu "JTextArea" w bibliotece "Swing".
DEFINIOWANIE ZDARZENIA PO EDYCJI TREŚCI WIELOWIERSZOWEGO POLA TEKSTOWEGO
"JTextArea" jak najbardziej wspiera te same zdarzenia zmiany zawartości i postępujemy identycznie, jak przy "JTextField 💪".
JCHECKBOX
Oprócz "tekstowych" spraw, na komponenty w "Swing" sprowadza się jeszcze pole wyboru, czyli "ptaszek" (ang. checkbox). Chodzi o przełączanie na "prawdę" lub "fałsz" ⏏️. Dzięki temu możemy "zerojedynkowo" kontrolować stan włączenia/wyłączenia i potem uzależniać działanie czegoś innego od aktualnej wartości 💡.
TWORZENIE POLA WYBORU
Przykładowy konstruktor ukazuje utworzenie pola wyboru z przypisanym łańcuchem znaków wyświetlanym obok ptaszka i domyślną wartością (włączone czy wyłączone) 👇:
var checkbox = new JCheckBox("Jestem polem wyboru", true);Po dodaniu do ramki możemy ujrzeć nasze pole wyboru, które domyślnie przyjmuje następujący kształt:
Wygląd komponentu "JCheckbox" w bibliotece "Swing".
DEFINIOWANIE ZDARZENIA PO PRZEŁĄCZENIU STANU W POLU WYBORU
Aby podłączyć jakieś instrukcje w momencie kliknięcia pola wyboru i zmiany stanu wartości (wł./wył.), wystarczy skorzystać z metody "addActionListener", dokładnie jak przy "JButton" ℹ️. Tak jak wtedy, możesz to zrobić przez klasę wewnętrzną, a jeszcze lepiej to zrobić przez wyrażenie lambda, które jest dużo prostsze w budowie 👇:
checkbox.addActionListener(event -> System.out.println(checkbox.isSelected()));JSLIDER
Kolejny komponent na liście to "JSlider" czyli po polsku "suwak" 🤐. Możliwość kontroli wartości liczbowej "jeżdżąc" paskiem od lewej do prawej.
TWORZENIE SUWAKA
Najbardziej podstawowy konstruktor nie wymaga jakichkolwiek parametrów i spowoduje utworzenie suwaka dopuszczającego wartość od 0 do 100 przy wartości początkowej równej 50 👇:
var slider = new JSlider();W efekcie czego mamy taki oto suwaczek, czyli tytułowy "JSlider":
Wygląd komponentu "JSlider" w bibliotece "Swing".
Uprzedzając pytanie: sam suwak nie zapewnia "licznika" aktualnej wartości. Należy dołożyć osobno obiekt "JLabel" i za pomocą podpięcia pod zdarzenie zmiany wartości, aktualizować tekst co każde "przesunięcie".
RODZAJE KONSTRUKTORÓW
"JSlider" możemy utworzyć na nieco bardziej "barwną" liczbę sposobów 🖌️.
Za pomocą poniższego zapisu, możesz zrobić suwak w orientacji pionowej 👇:
var slider = new JSlider(SwingConstants.VERTICAL);Używamy w tym miejscu "SwingConstants" - wbudowanego typu wyliczeniowego do określania orientacji poziomej (domyślnie) lub pionowej ⭐. Ponieważ za tym kryje się liczba całkowita "int", można wstawiać inne (niekoniecznie pasujące) wartości, jednak nie radzę - i to "IntelliJIDEA" też będzie Ci odradzał ⚠️! Lepiej korzystać z określonych wcześniej stałych ✅.
Inny konstruktor umożliwia definiowanie zakresu i początkowej wartości 🔥 - składa się on z 3 parametrów:
- wartość minimalna,
- wartość maksymalna,
- wartość początkowa.
Oto przykład:
var slider = new JSlider(0, 10, 1);To przypisze zakres: <0; 10> i nada wartość początkową równą 1.
DEFINIOWANIE ZDARZENIA PO ZMIANIE WARTOŚCI W SUWAKU
Postępujemy tak samo, jak przy przycisku ("JButton") i polu wyboru ("JCheckBox") - jedyna różnica jest w nazwie ℹ️. Metoda "addChangeListener" odpowiada za zdarzenie zmiany wartości podczas przeciągania suwaka. Znowu, dwa sposoby - klasa wewnętrzna bądź wyrażenie lambda 👇:
slider.addChangeListener(event -> System.out.println(slider.getValue()));JLIST
Kolejny z komponentów podstawowych, to lista z pozycjami do wyboru 🔢. Do tego służy "JList". Tu wyjątkowo, aby ujrzeć listę w oknie, trzeba wykonać 2 kroki 2️⃣.
TWORZENIE LISTY Z POZYCJAMI
Po pierwsze, utworzyć "DefaultListModel", czyli listę z pozycjami. Tworzymy obiekt i dodajemy do niego pozycje, jakie się mają znaleźć na liście 👇:
var defaultListModel = new DefaultListModel<String>();
defaultListModel.addElement("JLabel");
defaultListModel.addElement("JButton");
defaultListModel.addElement("JTextField");
defaultListModel.addElement("JTextArea");
defaultListModel.addElement("JCheckbox");
defaultListModel.addElement("JSlider");
defaultListModel.addElement("JList");Dopiero wtedy, mając tak przygotowaną listę, wprowadzamy ją jako parametr do instancji "JList":
var list = new JList<>(defaultListModel);Powyższe operacje spowodują ukazanie się oto takiej listy ze wszystkimi zdefiniowanymi w modelu elementami:
![]() |
Wygląd komponentu "JList" w bibliotece "Swing".
DEFINIOWANIE ZDARZENIA PO ZMIANIE ZAZNACZONEJ POZYCJI W LIŚCIE
Gdyby Cię interesowało przechwycenie zdarzenia zmiany zaznaczonej pozycji w liście, to korzystasz z metody "addListSelectionListener". Zasada jest taka sama, jak w każdym poprzednio wymienionym komponencie - tworzysz sobie albo klasę wewnętrzną, albo sięgasz po wyrażenie lambda, które oszczędzi Ci długiego pisania 😅:
list.addListSelectionListener(event -> {
if(!list.getValueIsAdjusting()) {
System.out.println(list.getSelectedIndex());
}
});Tutaj wyjątkowo musimy zrobić pewien "myk", który powoduje podwójne wykonywanie instrukcji ⚠️! Wszelkie instrukcje umieszczamy w warunku:
!list.getValueIsAdjusting()To ma na celu zapobiec reagowaniu na sytuację samego naciśnięcia dowolnej pozycji w liście przy użyciu lewego przycisku myszy. Nam przyda się jedynie moment puszczenia przycisku, czyli to co robimy automatycznie podczas klikania myszką w dowolne miejsce na monitorze 💻.
JCOMBOBOX
Ostatnie zdania na temat odmiany listy "zwykłej" - listy rozwijanej. Tutaj Java robi psikusa i to nosi zupełnie inną nazwę, niż jaka mogła Ci przyjść do głowy 😜. Lista rozwijana, to w "Swing" nazywa się "JComboBox" 😱.
TWORZENIE LISTY ROZWIJANEJ
Jeżeli chodzi o "JComboBox", tutaj również musimy najpierw utworzyć model z danymi. Tym razem posługujemy się "DefaultComboBoxModel", natomiast dodajemy wartości w taki sam sposób, co poprzednio 👇:
var defaultComboBoxModel = new DefaultComboBoxModel<String>();
defaultComboBoxModel.addElement("JLabel");
defaultComboBoxModel.addElement("JButton");
defaultComboBoxModel.addElement("JTextField");
defaultComboBoxModel.addElement("JTextArea");
defaultComboBoxModel.addElement("JCheckbox");
defaultComboBoxModel.addElement("JSlider");
defaultComboBoxModel.addElement("JList");
defaultComboBoxModel.addElement("JComboBox");następnie tworzymy obiekt samej listy rozwijanej i wprowadzamy do niego nasz model:
var comboBox = new JList<>(defaultComboBoxModel);W efekcie czego, nasze wysiłki dadzą nam taki efekt:
![]() |
Wygląd komponentu "JComboBox" w bibliotece "Swing".
Normalnie cała lista jest ukryta i elementy odkrywają się dopiero po kliknięciu strzałki po prawej stronie ✅.
DEFINIOWANIE ZDARZENIA PO WYBRANIU POZYCJI Z LISTY ROZWIJANEJ
Metoda "addActionListener" pozwala na określenie co ma się wydarzyć po wybraniu dowolnej pozycji z listy ▶️. Ten sam sposób, co pokazano wcześniej (wyrażenie lambda) 👇:
comboBox.addActionListener(event -> System.out.println(comboBox.getSelectedIndex()));Małe wtrącenie na temat słowa kluczowego "var" - ono pozwala Tobie uniknąć każdorazowego wprowadzania ręcznie typu danych tworzonej zmiennej. O ile kompilator jest w stanie wywnioskować typ na podstawie informacji "stojących obok", możesz dzięki temu uprzyjemnić sobie pisanie ❤️!
Takie oto występują podstawowe komponenty w "Swing" 👍.
NASTĘPNY ARTYKUŁ: Układ w Swing. Konfiguracja pozycjonowania komponentów



