Zajęcia 8. - Graficzne interfejsy użytkownika - Swing
Swing - wprowadzenie
- Swing to biblioteka GUI w pakiecie
javax.swing - Część Java Foundation Classes (JFC)
- Zbudowany na AWT, ale komponenty Swing są rysowane głównie w Javie (lightweight)
- Spójny wygląd na różnych systemach operacyjnych
- Bogatszy zestaw kontrolek niż klasyczne AWT
- Dokumentacja: javax.swing (Java SE)
Swing i AWT - podobieństwa
- Te same fundamenty: okna, komponenty, kontenery, layouty
- Ten sam model zdarzeń (listener, event object, źródło zdarzenia)
- Często używane razem klasy z
java.awt(np.BorderLayout,Color,Font) - Główne okno nadal opiera się o
java.awt.Window(np.JFrame)
Swing i AWT - różnice
- AWT: komponenty natywne (heavyweight), Swing: głównie lekkie komponenty
- Swing ma osobny model prezentacji (UI delegate, Look & Feel)
- Swing oferuje więcej gotowych kontrolek i modeli danych
- W Swing łatwiej utrzymać spójność UI między platformami
- Rysowanie po komponentach przez
paintComponent(Graphics g) - W praktyce: nowe GUI desktopowe w Javie zwykle robimy w Swing (lub JavaFX)
Hierarchia Swing - najważniejsze klasy
Component→Container→JComponentJComponentto baza większości kontrolek Swing (JButton,JLabel,JTable…)- Top-level containers:
JFrame- główne oknoJDialog- okno dialogoweJWindow- okno bez ramek systemowych
- Każdy top-level container ma
JRootPanez trzema głównymi panelami:glassPane(szklany),layeredPane(warstwowy),contentPane(treści)
Top-level containers
glassPane- przezroczysta warstwa nad wszystkimi panelami (np. do rysowania, obsługi zdarzeń globalnych)layeredPane- warstwy Z-order (kolejność ułożenia komponentów)contentPane- główny obszar, gdzie dodajesz komponenty- opcjonalnie
menuBar - Najczęściej pracujesz z
contentPaneprzezframe.add(…)lubframe.getContentPane().add(…)
JFrame frame = new JFrame("Warstwy Swing"); JComponent glass = (JComponent) frame.getGlassPane(); glass.setVisible(false); // np. true gdy chcemy overlay Container content = frame.getContentPane(); content.setLayout(new BorderLayout()); content.add(new JLabel("Treść główna"), BorderLayout.CENTER);
Pierwsze okno Swing
- Tworzenie GUI uruchamiaj na EDT (Event Dispatch Thread) - wątek odpowiedzialny za obsługę zdarzeń i rysowanie
- Ustaw
setDefaultCloseOperation(…)naJFrame.EXIT_ON_CLOSE, aby zamknąć aplikację po zamknięciu okna pack()- dopasuj rozmiar do zawartości
import javax.swing.*; import java.awt.*; public class HelloSwing extends JFrame { public HelloSwing() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); add(new JLabel("Witaj, Swing!", SwingConstants.CENTER), BorderLayout.CENTER); pack(); setLocationRelativeTo(null); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { HelloSwing frame = new HelloSwing(); frame.setVisible(true); }); } }
Kontrolki Swing - szybki przegląd
- Tekst i input:
JLabel,JTextField,JTextArea,JPasswordField - Wybór:
JCheckBox,JRadioButton,JComboBox,JList - Akcje:
JButton,JToggleButton,JMenuItem,JToolBar - Dane złożone:
JTable,JTree - Kontenery:
JPanel,JScrollPane,JTabbedPane,JSplitPane - Dialogi:
JOptionPane,JFileChooser,JColorChooser JScrollBar,JSeparator,JProgressBar,JSlider,JSpinner, …
Obsługa zdarzeń
- Użytkownik wykonuje akcję na komponencie (źródło zdarzenia)
- Swing tworzy obiekt zdarzenia (np.
ActionEvent) - Zarejestrowany listener odbiera callback
JButton btn = new JButton("Policz"); JTextField input = new JTextField(10); JLabel out = new JLabel("Wynik: -"); btn.addActionListener(e -> { String text = input.getText().trim(); out.setText("Wynik: " + text.length()); });
Layout Managers
java.awt.BorderLayout- 5 regionów: NORTH, SOUTH, EAST, WEST, CENTERjava.awt.FlowLayout- komponenty od lewej do prawejjava.awt.GridLayout- siatka równych komórekjava.awt.CardLayout- przełączanie widokówjava.awt.GridBagLayout- najbardziej elastyczny (i najbardziej złożony)javax.swing.BoxLayout- pionowo/poziomojavax.swing.SpringLayout- układ sprężynowyjavax.swing.GroupLayout- używany przez GUI Designer
Swing GUI Designer
- Wtyczka do IntelliJ IDEA do projektowania interfejsów metodą drag-and-drop
- Definicja UI w pliku
.form(XML) - Logika aplikacji pozostaje w
.java - Zalety: szybki prototyp, mniej ręcznego ustawiania layoutów
- Uwaga: nie edytuj ręcznie
.form, jeśli nie musisz - Tworzenie aplikacji: Utwórz formę i ustaw
setContentPane(panel)wskazując na główny panel z GUI Designer
Look & Feel - dostosowanie wyglądu
- Każdy komponent Swing ma delegata UI (np.
ButtonUI) odpowiedzialnego za rysowanie i zachowanie - Look & Feel (LAF) to zestaw delegatów definiujący styl i zachowanie komponentów
- Wbudowane LAF: Metal, Nimbus, System
- LAF ustawiaj przed tworzeniem komponentów
- Pobranie i ustawienie LAF:
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } }
Akcje Swing (Action API)
Actionłączy logikę i metadane akcji (tekst, ikona, skrót, enabled)- Jedna akcja może być podpięta do wielu komponentów
- Centralizacja logiki: przycisk, menu, toolbar używają tego samego kodu
- Parametry:
Action.NAME,Action.SHORT_DESCRIPTION,Action.SMALL_ICON,Action.ACCELERATOR_KEY
Action saveAction = new AbstractAction("Zapisz") { @Override public void actionPerformed(ActionEvent e) { System.out.println("Zapis..."); } }; saveAction.putValue(Action.SHORT_DESCRIPTION, "Zapisz dane"); JButton saveBtn = new JButton(saveAction); JMenuItem saveItem = new JMenuItem(saveAction);
MVC w Swing
- Swing był projektowany z myślą o MVC, ale jego komponenty same w sobie są hybrydą View + Controller
- Przykład:
JButton' ma własnyButtonModel' (Model) i własne listenery (Controller), a Ty dostarczasz logikę. - Komponenty są powiązane z modelem danych (np.
JTablezTableModel), dane trzymasz w modelu, a komponent tylko je wyświetla
Modele danych w Swing
Dane trzymasz w modelu, a komponent tylko je wyświetla.
| Komponent | Interfejs modelu | Domyślna implementacja | Opis |
|---|---|---|---|
JList | ListModel | DefaultListModel | Lista elementów |
JTable | TableModel | DefaultTableModel | Tabela wierszy i kolumn |
JComboBox | ComboBoxModel | DefaultComboBoxModel | Lista rozwijana |
JTree | TreeModel | DefaultTreeModel | Drzewo węzłów |
JTextField, JTextArea | Document | PlainDocument | Treść pola tekstowego |
JProgressBar, JSlider, JScrollBar | BoundedRangeModel | DefaultBoundedRangeModel | Wartość w zakresie min–max |
JSpinner | SpinnerModel | SpinnerNumberModel | Wartość incrementalna |
JButton, JCheckBox, JRadioButton | ButtonModel | DefaultButtonModel | Stan przycisku (wciśnięty, zaznaczony) |
Przykład
DefaultListModel<String> listModel = new DefaultListModel<>(); listModel.addElement("Ala"); listModel.addElement("Ola"); JList<String> list = new JList<>(listModel); DefaultTableModel tableModel = new DefaultTableModel( new Object[]{"ID", "Nazwa"}, 0 ); tableModel.addRow(new Object[]{1, "Klient"}); JTable table = new JTable(tableModel);
MVC w Swing
* Model — czysta logika i dane (np. stan aplikacji, obliczenia, walidacja) * View — komponenty Swing (JFrame, JPanel, JButton, JTable) * Controller — listenery, które reagują na zdarzenia i wywołują metody modelu
MVVM-like w Swing + PropertyChangeListener
- Swing nie ma natywnego MVVM jak JavaFX, ale można zrobić wariant
- ViewModel publikuje zmiany przez
PropertyChangeSupport - View nasłuchuje i aktualizuje kontrolki
class PersonViewModel { private final java.beans.PropertyChangeSupport pcs = new java.beans.PropertyChangeSupport(this); private String name = ""; public void setName(String newName) { String old = this.name; this.name = newName; pcs.firePropertyChange("name", old, newName); } public void addPropertyChangeListener(java.beans.PropertyChangeListener l) { pcs.addPropertyChangeListener(l); } }
Zadanie 7: Kalkulator w Swing
Utwórz prosty kalkulator wykorzystujący Swing dla języka Java.
Wymagania:
- Obsługa podstawowych działań: dodawanie, odejmowanie, mnożenie, dzielenie
- Obsługa liczb niecałkowitych (np. 3.14)
- Zamiana na liczbę ujemną (±)
- Czyszczenie (C)
- Przechowuj aktualną wartość i ostatnią operację, aby umożliwić ciągłe obliczenia
- Interfejs inspirowany kalkulatorem systemu Windows
Przykładowy wygląd aplikacji:




