Programowanie Obiektowe – 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. Informacje o komponentach, zdarzeniach, wyglądzie i układzie elementów w technologii Swing można znaleźć na stronie: http://download.oracle.com/javase/tutorial/uiswing/ 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.

5. Zaznacz w oknie 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” i tekst przycisku na „Count”. (Sic!) Zwróć uwagę na panel Navigator 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 wybrać je w Panelu Navigator.

7. Ponownie korzystając z palety właściwości, ale tym razem z 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 grot obok tekstu przy zdarzeniu actionPerformed. Kliknij w proponowaną nazwę zdarzenia (countButtonActionPerformed). c. Netbeans powinien przełączyć się w tryb edycji kodu 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. c. d. e. f. g.

odszukaj na dysku katalog, w którym zapisany jest projekt NetBeans odszukaj archiwum JAR z aplikacją w podkatalogu dist dwuklikiem otwórz aplikację uruchom okno wiersza poleceń systemu operacyjnego przejdź w wierszu poleceń do podkatalogu dist katalogu projektu spróbuj uruchomić aplikację poleceniem: java -jar SwingCounter.jar

JavaFX Obecnie, producenci Javy promują nową technologię tworzenia GUI – JavaFX. JavaFX pozwala na tworzenie interfejsu użytkownika nie tylko w kodzie, ale również za pomocą języka znaczników FXML oraz arkuszy CSS. Poniższa kroki pokażą jak stworzyć prosty interfejs z wykorzystaniem języka FXML, ale istnieje również możliwość „wyklikania” interfejsu. Do tego celu potrzebna jest aplikacja Scene Builder. Informacje jak można korzystać z Scene Buildera w aplikacjach Netbeans i Eclipse, można znaleźć pod adresem: https://blogs.oracle.com/jeromec/entry/integrating_javafx_scene_builder_in Ogólne informacje o komponentach, zdarzeniach, wyglądzie i układzie elementów aplikacji wykorzystujących JavaFX można znaleźć na stronie: http://docs.oracle.com/javafx/ 1. Stwórz nowy projekt typu JavaFX FXML Application

2. W następnym oknie, nazwij projekt JavaFXCounter, pozostaw wszystkie domyślne wartości opcji bez zmian i kliknij Finish. 3. Rozwiń folder z plikami źródłowymi projektu, zaznacz plik FXMLDocument i z menu kontekstowego wybierz opcję Edit.

4. W edytorze powinna się otworzyć definicja układu graficznego w języku FXML. Kolejne komponenty graficzne można zagnieżdżać w sobie za pomocą odpowiednich znaczników. Informacje dotyczące obsługi zdarzeń oraz wyglądu komponentów zawarte są w atrybutach znaczników. 5. Zmień tekst wyświetlany na przycisku na „Count”, ustaw tekst etykiety na „0” oraz zmień nazwę przycisku i etykiety odpowiednio na countButton i counterLabel.

6. Przejdź do pliku kontrolera (FXMLDocumentController). Zwróć uwagę że jego nazwa była podana w pliku FXML w atrybucie fx:controller. 7. Zmień nazwę pola label na counterLabel. 8. Zmień kod metody handleButtonAction (zwróć uwagę że nazwa tej metody również została wskazana w pliku FXML) na następujący: counterLabel.setText(Integer.toString( Integer.parseInt(counterLabel.getText())+1)); 9. Uruchom aplikację i sprawdź czy działa.

Zadania 1. Proszę zaprojektować okno informacyjne prezentujące podstawowe informacje o handlarzu/legionie/plemieniu. 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 (wzór dotyczy przykładu z zajęć). CounterJFrame counter = new CounterJFrame(); counter.setVisible(true); try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelCla ssName()); } catch (Exception ex) { System.out.println(ex); } SwingUtilities.updateComponentTreeUI(counter); Oprócz zmiany wyglądu GUI na zgodny z systemem operacyjnym Java oferuje kilka innych opcji. Pełna lista przykładem na stronie: http://wazniak.mimuw.edu.pl/index.php?title=PO_Graficzny_interfejs_u%C5%BCytkownika