Programowanie Obiektowe
– Projektowanie GUI
Swing
Celem ćwiczenia jest ilustracja wizualnego tworzenia graficznego interfejsu użytkownika
opartego o bibliotekę Swing w środowisku NetBeans. Ponadto, ćwiczenie ma na celu
pokazanie i wyjaśnienie wykorzystania anonimowych klas wewnętrznych w programach
korzystających z biblioteki Swing. Ostatnim krokiem ćwiczenia jest przygotowanie aplikacji
do dystrybucji i jej uruchomienie z poziomu systemu operacyjnego.
1. Uruchom środowisko NetBeans.
2. Utwórz nowy projekt:
a) W pierwszym kroku kreatora jako typ projektu wybierz Java Application z kategorii Java.
b) W drugim kroku kreatora jako nazwę projektu podaj SwingCounter i odznacz pole wyboru
tworzenia głównej klasy.
3.Utwórz w projekcie okno główne aplikacji kreatorem JFrame Form. Jako nazwę klasy podaj
CounterJFrame
, a jako nazwę pakietu count.
4. Techniką drag’n’drop umieść w oknie aplikacji etykietę tekstową (Label) oraz przycisk
(Button). Następnie przesuń krawędzie okna aby zmniejszyć je dopasowując je do zawartości.
5. Zaznacz w oknie graficznej edycji aplikacji okno główne i korzystając z palety właściwości
(Properties) zmień jego tytuł (title) na „Counter Demo”.
6. Analogicznie do pkt. 5 zmień tekst (text) etykiety na „0” a tekst (text) na przycisku na
„Count”.
(Sic!) Zwróć uwagę na panel Inspector w lewym dolnym rogu Netbeansa. Widać w nim
drzewo komponentów aktywnego JFrame’a. Poprzez wybieranie elementów drzewa można
ustawiać elementy jako aktywne bez wyszukiwania ich w edytorze graficznym. Funkcja ta
jest bardzo przydatna gdy komponenty są bardzo małe lub przesłonięte przez inny
komponent. Ponadto niektóre komponenty jak Dialog, JFrame czy QueryResult nie są
widoczne w edytorze graficznym i aby edytować ich właściwości należy najpierw wybrac je
w Panleu Inspector.
7. Ponownie korzystając z palety właściwości, ale tym razem z jej zakładki Code, zmień
nazwę zmiennej reprezentującej etykietę (Variable Name) na counterLabel, a nazwę
zmiennej dla przycisku na countButton.
8. Przełącz edytor z trybu Design w tryb Source i przeanalizuj kod wygenerowany przez
graficzną edycję aplikacji:
a) sprawdź z jakiej klasy dziedziczy klasa okna głównego naszej aplikacji
b) odszukaj w definicji klasy zmienne instancji reprezentujące etykietę i przycisk. Zwróć
uwagę na ich typy
c) odszukaj instrukcje ustawiające tytuł okna oraz teksty na etykiecie i przycisku
d) zwróć uwagę na sposób utworzenia obiektu okna w metodzie main().
Wyjaśnienie: Komponenty Swing, m.in. ze względów efektywnościowych, nie są
przystosowane do ich wykorzystywania przez wiele wątków programu. Dlatego dla
bezpieczeństwa, a także zwiększenia responsywności aplikacji, wszelkie operacje na
komponentach Swing powinny być realizowane przez wyróżniony wątek obsługi zdarzeń.
Zadanie do wykonania w ramach tego wątku można zlecić metodą invokeLater klasy
java.awt.EventQueue (lub javax.swing.SwingUtilities). Parametrem
przekazywanym do metody jest obiekt klasy implementującej interfejs Runnable. Ponieważ
klasa ta służy tylko do utworzenia jednego obiektu, można zdefiniować ją jako anonimową
klasę wewnętrzną w miejscu, w którym jest tworzony jej obiekt. Konstrukcja
new Runnable() {...} tworzy obiekt anonimowej klasy implementującej interfejs
Runnable
. W nawiasach klamrowych zawarte są implementacje metod tej anonimowej
klasy (w naszym przypadku jedna).
9. Ustaw klasę okna aplikacji jako główną klasę projektu:
a) Wywołaj okno właściwości projektu wybierając opcję Properties z menu kontekstowego
dla węzła projektu
b) Przejdź do sekcji Run i przyciskiem Browse wybierz klasę główną
10. Uruchom projekt. Sprawdź działanie aplikacji (oczywiście licznik jeszcze się nie
zwiększa). Zamknij aplikację.
11. Zaimplementuj zwiększanie licznika po naciśnięciu przycisku:
a) Przełącz się w tryb Design edycji kodu klasy okna głównego aplikacji
b) Przejdź do edycji właściwości przycisku. Przełącz się na zakładkę Events palety
właściwości. Kliknij w tekst <none> w miejscu nazwy metody dla zdarzenia
actionPerformed. Powinna pojawić się w polu nazwa metody utworzonej przez kreator.
c) Przełącz się w tryb Source edycji kodu klasy okna głównego aplikacji. Odszukaj
wygenerowaną metodę obsługi zdarzenia i jako jej ciało wprowadź poniższy kod:
counterLabel.setText(Integer.toString(
Integer.parseInt(counterLabel.getText())+1));
Wyjaśnienie: Etykieta zawiera wartość tekstową. Aby potraktować ją jako liczbę i zwiększyć
o 1 należy dokonać jej konwersji na typ int, a po zwiększeniu z powrotem na String.
d) Odszukaj w kodzie powiązanie metody obsługującej zdarzenie kliknięcia przycisku z
przyciskiem. Spróbuj zinterpretować ten mechanizm
Wyjaśnienie: Z komponentami generującymi zdarzenia wiązane są obiekty implementujące
odpowiedni interfejs. Dla przycisku jest to interfejs ActionListener zawierający metodę
actionPerformed
. Wygenerowany przez kreator kod tworzy obiekt nasłuchujący na
zdarzenie z przycisku jako obiekt anonimowej klasy implementującej interfejs
ActionListener. Implementacja metody actionPerformed w tej klasie sprowadza
się do wywołania metody zewnętrznej klasy okna aplikacji zawierającej napisany przez
programistę kod obsługi zdarzenia. Rozwiązanie to ilustruje ważną zaletę anonimowych klas
wewnętrznych – ich obiekty mają dostęp do wszystkich składowych obiektu klasy
zewnętrznej.
12. Zapisz wszystkie zmiany. Uruchom aplikację, przetestuj ją, a następnie zamknij.
13. Uruchom aplikację z systemy plików/wiersza poleceń:
a) przygotuj aplikację do dystrybucji wybierając opcję Build z menu kontekstowego dla
projektu (lub wciśnij klawisz F11)
b) odszukaj na dysku katalog, w którym zapisany jest projekt NetBeans
c) odszukaj archiwum JAR z aplikacją w podkatalogu dist
d) dwuklikiem otwórz aplikację
e) uruchom okno wiersza poleceń systemu operacyjnego
f) przejdź w wierszu poleceń do podkatalogu dist katalogu projektu
e) spróbuj uruchomić aplikację poleceniem:
java -jar SwingCounter.jar
Zadania
1. Proszę zaprojektować okno informacyjne prezentujące podstawowe informacje o pojeździe, tak jak
przedstawiono na rysunku poniżej:
2. Przygotuj program wyświetlający przycisk, który po najechaniu na niego myszką zmienia
położenie. Zmiana położenia ma uniemożliwić kliknięcie na przycisk.
3. Proszę zmienić implementację metody run() na wzór podany poniżej:
CounterJFrame counter = new CounterJFrame();
counter.setVisible(true);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
System.out.println(ex);
}
SwingUtilities.updateComponentTreeUI(counter);
Oprócz zmiany wyglądu GUI na zgodny z systemem operacyjnym Java oferuje kilk innych opcji.
Pełna lista przykładem na stronie:
http://wazniak.mimuw.edu.pl/index.php?title=PO_Graficzny_interfejs_u%C5%BCytkownika