Post on 15-Jul-2019
Programowanie w języku Java
WYKŁAD
dr inż. Piotr Zabawa
Certyfikowany Konsultant IBM/Rational
e-mail: pzabawa@pk.edu.pl
www: http://www.pk.edu.pl/~pzabawa 12.05.2014
Zakład Inżynierii Oprogramowania
WYKŁAD 11GUI w Swing – cz. 2
Wykład został w znacznej mierze
opracowany na podstawie:http://edu.pjwstk.edu.pl/wyklady/poj/scb/PrgGui1/PrgGui1.html#PrgGui1
http://edu.pjwstk.edu.pl/wyklady/poj/scb/RozSwi/RozSwi.html#RozSwi
http://edu.pjwstk.edu.pl/wyklady/poj/scb/MVC/MVC.html#MVC
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Zasady działania na komponentach GUI:
• Komponenty tworzymy za pomocą wyrażenia new wywołującego odpowiedni
konstruktor klasy komponentu, któremu podajemy argumenty, określające niektóre
właściwości komponentu (np. tekst/ikonę na przycisku).
• Komponenty mają właściwości (np. kolory, pismo tekstu na przycisku), które możemy
ustalać (lub pobierać) za pomocą metod z odpowiednich klas komponentów (metody
setNNN(...), getNNN(...), isNNN(...), gdzie NNN nazwa właściwości).
• Większość właściwości komponentów jest reprezentowane przez obiekty odpowiednich
klas (np. pismo – klasa Font, kolor – klasa Color)
• Komponenty, które mogą zawierać inne komponenty nazywają się kontenerami.
• Do kontenerów dodajemy inne komponenty (w tym inne kontenery)
• Z każdym kontenerem związany jest określony zarządca rozkładu, który określa układ
komponentów w kontenerze i ich zachowanie (zmiany rozmiarów i położenia) przy
zmianie rozmiarów kontenera. Inaczej: rozkład jest jedną z właściwości kontenera.
• Zarządcy rozkładu są obiektami odpowiednich klas
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
• Dla każdego kontenera możemy ustalić wybranego zarządcę rozkładu
• Aplikacja komunikuje się z użytkownikiem za pomocą okna lub wielu okien
• Okna AWT są kontenerami, do których dodajemy komponenty wizualnej
interakcji z użytkownikiem (w tym inne kontenery)
• Okna Swingu zawierają tzw. contentPane, który jest kontenerem do którego
domyślnie dodajemy komponenty wizualnej interakcji (w tym inne kontenery).
• Okna (w tym "okno" apletu) są zawsze kontenerami najwyższego poziomu w
hierarchii zawierania się komponentów
• Współdziałanie użytkownika z aplikacją odbywa się na zasadzie obsługi
zdarzeń (np. zdarzenia kliknięcia w przycisk). Obsługą zdarzeń zarządza
specjalny, równolegle z naszym programem wykonujący się kod w JVM –
wątek obsługi zdarzeń. O obsłudze zdarzeń – w następnym wykładzie.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
Ograniczenia AWT, dla których pokonania opracowano Swing:
• ubogie możliwości graficzne i interakcyjne komponentów,
• brak komponentów istotnych dla oprogramowania nowoczesnych GUI
(np. tabel)
• zależny od platformy systemowej wygląd komponentów
Umiejscowienie pakietu AWT:
• java.awt
Kolejny ważny problem AWT, to fakt, że komponenty końcowe
(powoływane do życia w aplikacjach) są komponentami ciężkimi.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
Zalety Swing:
• Rozbudowanie istniejących komponentów AWT
• Wprowadzenie nowych komponentów AWT
Odpowiednie rozdzielone hierarchie zostaną pokazane dalej.
Umiejscowienie pakietu Swing:
• javax.swing
Kolejna cech charakterystyczna Swing, to fakt, że wszystkie
komponenty Swing z wyjątkiem znajdujących się najwyżej w hierarchii są
komponentami lekkimi.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
Komponenty ciężkie są realizowane poprzez użycie graficznych
bibliotek GUI systemu operacyjnego.
Komponenty lekkie są natomiast rysowane za pomocą kodu Javy w
obszarze jakiegoś komponentu ciężkiego znajdującego się wyżej w
hierarchii zawierania się komponentów (zwykle jest to kontener
najwyższego poziomu).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
Znaczenie tego gdzie lepiej w hierarchii umieścić klasy lekkie a gdzie
ciężkie można prawidłowo i ogólnie zrozumieć studiując wzorce
projektowe:
• Strategia
• Dekorator
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
Zatem komponenty lekkie:
• mogą być przezroczyste, a zatem mogą przybierać wizualnie dowolne
kształty
• mają wygląd niezależny od platformy.
Lekkie komponenty Swingu spełniają oba te warunki, a architektura
klas Swingu pozwala wybierać wygląd jego lekkich komponentów
(pluggable look and feel).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
UWAGA: da się mieszać ze sobą komponenty ciężkie AWT i lekkie
Swing poprzez umieszczenie ich w tym samym kontenerze, ale nie jest to
zalecane. Powoduje to problemy z prawidłową obsługą kolejności
nakładania na siebie elementów GUI w osi Z (Z-order). Ze względu na ten
problem zdecydowano się opracować dość złożoną strukturę okien w
Swing. Dlatego w Swing należy dodawać komponenty do ContentPane
okna JFrame.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
Poniżej przedstawiono na diagramie klas związki między AWT i
Swing.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
Komponenty Swingu o rozbudowanych możliwosciach w stosunku do
AWT (AWT ma swoje odpowiedniki)
[Źródło: Magellan Institute Swing Short Course.]
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – AWT/Swing
Hierarchia klas komponentów Swingu, nie mających odpowiedników
w AWT
[Żródło: Magellan Institute Swing Short Course.]
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – kontenery
• Panel: klasa JPanel
służy do grupowania komponentów
• Panel dzielony: klasa JSplitPane
podział kontenera na dwie części (poziomo lub pionowo) z
możliwością przesuwania belki podziału dla ustalenia rozmiarów
widoków części
• Panel zakładkowy: klasa JTabbedPane
zakładki służą do wybierania komponentów, które mają być
uwidocznione w panelu
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – kontenery
• Panel przewijany: klasa JScrollPane
służy do pokazywania komponentów, które nie mieszczą się w polu
widoku; suwaki umożliwiają "przewijanie" widoku komponentu, tak,
by odsłaniać kolejne jego fragmenty.
JTextArea i JList powinny być umieszczane w JScrollPane, jeśli ich
zawartość (wiersze tekstu, elementy listy) może się powiększać.
Pasek narzędzi: klasa JToolBar
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – komponenty
Lista własności wszystkich komponentów Swing:
• rozmiar (Size)
• szerokość (Width)
• wysokość (Height)
• położenie (Location)
• rozmiar i położenie (Bounds)
• minimalny rozmiar (MinimumSize)
• preferowany rozmiar (PreferredSize)
• mksymalny rozmiar (MaximumSize)
• wyrównanie po osi X (AlignmentX)
• wyrównanie po osi Y (AlignmentY)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – komponenty
• pismo (Font)
• kolor tła (Background)
• kolor pierwszego planu (Foreground)
• rodzic (Parent)
• nazwa (Name)
• widzialność (Visible)
• lekkość (LigthWeight)
• przezrosczystość (Opaque)
• dostępność (Enabled).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
UWAGI:
• Rozmiary komponentów znane są dopiero po spakowaniu metodą
pack() okna zawierającego te komponenty
• Położenie komponentu określane jest przez współrzędne (x,y), a punkt
(0,0) oznacza lewy górny róg obszaru w którym znajduje się komponent
• Zmiana położenia i rozmiarów za pomocą metod set ma w zasadzie
sens tylko dla komponentów znajdujących się w kontenerach bez zarządcy
rozkładu lub dla komponentów-okien.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Pismo jest obiektem klasy Font, tworzonym za pomocą konstruktora
Font(nazwa_pisma, styl, rozmiar)
gdzie:
• nazwa_pisma - jest łańcuchem znakowym, określającym rodzaj pisma
(np. "Dialog")
• styl - jest jedną ze stałych statycznych typu int z klasy Font:
Font.BOLD
Font.ITALIC
Font.PLAIN
(kombinacje uzyskujemy np. jako Font.BOLD | Font.ITALIC)
• rozmiar - liczba całkowita określająca rozmiar pisma w punktach.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Kolor jest obiektem klasy Color, która ma kilka konstruktorów oraz
udostępnia stałe statyczne typu Color z predefiniowanymi kolorami, np.
Color.red, Color.blue, Color.white...
Kolory przycisku możemy więc ustalić za pomocą takich konstrukcji:
b.setBackground(Color.blue);
b.setForeground(Color.white);
albo:
int r, g, b;
r = 200; g = 200; b = 255;
b.setBackground(new Color(r,g,b));
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Zablokowanie/odblokowanie komponentu
b.setEnabled(false); // zablokowanie
b.setEnabled(true); // odblokowanie
Zablokowanie komponentu powoduje, że nie jest on zdolny do
przyjmowania zdarzeń.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Ukrywanie/uwidacznianie komponentów
b.setVisible(false); // stanie się niewidoczny
b.setVisible(true); // stanie się widoczny
Komponent po ukryciu staje się niewidoczny na ekranie. Wszystkie
komponenty z wyjątkiem wywodzących się z klasy Window są domyślnie
widoczne. Dodanie komponentu do wcześniej uwidocznionego kontenera
powoduje pojawienie się tego komponentu.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Ustawianie/wyłączanie przeźroczystości
Wszystkie komponenty AWT są nieprzeźroczyste.
Przeźroczystością wszystkich komponentów Swing można sterować.
Wszystkie komponenty Swing z wyjątkiem JLabel są domyślnie
nieprzeźroczyste.
setOpaque(true); // komponent stanie się nieprzeźroczysty
setOpaque(false); // komponent stanie się przeźroczysty
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Odświeżanie komponentu Swing
Jest ono realizowane za pomocą odwołań zwrotnych (callback)
inicjowanych przez JVM a skierowanych do metody paint() komponentu
zaimplementowanej w klasie JComponent. Metody tej nie wolno
wywoływać z kodu aplikacji, można ją jedynie przesłonić własną
implementacją. Jeśli istnieje konieczność odrysowania komponentu przez
aplikację, to należy użyć metody repaint(...).
Przedefiniowanie metod paint():
• w AWT należy przedefiniować public void paint(Graphics),
• w Swingu – metodę public void paintComponent(Graphics).
Ostatnie z powyższych rozwiązań jest jednak nieeleganckie.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
W metodzie paint() jednym z argumentów jest referencja do obiektu
klasy Graphics. Obiekt ten reprezentuje tzw. kontekst graficzny danego
komponentu.
Kontekst graficzny jest swoistym logicznym "urządzeniem
wyjściowym". Zwykle jest to ekran komputera, ale może to być np.
wydruk lub bufor w pamięci. Logiczny kontekst graficzny może więc być
związany z różnymi "urządzeniami wyjściowymi" na których "rysowany"
jest komponent.
Aby zagwarantować odpowiedni wygląd i funkcjonalność gotowych
komponentów, których klasy dziedziczymy, w przedefiniowywanej
metodzie paintComponent należy na początku wywołać metodę
paintComponent z nadklasy.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Wyprowadzanie napisów w Swing
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing - grafika
Rysowanie obrazu z pliku
Dostęp do obrazu z pliku możemy uzyskać za pomocą odwołania:
Image img = Toolkit.getDefaultToolkit().getImage(nazwa_pliku);
Wykreślaniem obrazu w obszarze komponentu wizualnego zajmuje się
metoda drawImage z klasy Graphics.
Ładowanie i wyświetlanie dużych obrazów w Swing wygląda
nieładnie – dług trwa i obraz ładuje się etapami. Wprowadzono więc dwie
klasy:
• ImageObsrever
• MediaTracker
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
okno wtórne (secondary window, child window) = okno które ma właściciela - inne okno
okno pierwotne, właściciel innych okien (owner) = okno, które jest właścicielem innych okien
Skutki prawa własności:
• zamknięcie okna pierwotnego powoduje zamknięcie okien wtórnych, które są jego własnością,
• minimalizacja okna pierwotnego powoduje minimalizację okien wtórnych,
• przesunięcie okna pierwotnego powoduje przesunięcie okien wtórnych (nie na wszystkich
platformach)
Okno wtórne może być oknem modalnym lub nie.
Modalność oznacza, iż interakcja z oknem pierwotnym jest zablokowana do chwili zamknięcia okna
wtórnego.
Przy niemodalnym oknie wtórnym - możemy dalej działać na oknie pierwotnym.
Z - order = uporządkowanie okien "po osi Z" (czyli jak się okna na siebie nakładają).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Klasy okien:
• JWindow – może zostać użyte do utworzenia skastomizowanych okien
o następujących cechach:
– okno bez ramki, menu i tytułu
– ma właściciela - inne okno
– nie podlega przesunięciom wraz z właścicielem
– nie jest modalne
• JFrame - może zostać użyte do skonstruowania okien, które:
– nie mają właściciela
– nie są modalne
Zwykle jest nim główne okno aplikacji (nie ma właściciela!).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
• JDialog – służy do konstruowania okien o następujących cechach:
– ma ramkę
– ma tytuł
– ma właściciela
– nie może mieć paska menu
– może, ale nie musi być modalne
Przeznaczone jest wyłącznie do tworzenia okienek dialogowych.
• JInternalFrame – okna wewnętrzne są lekkimi komponetami o funkcjonalności
okien ramowych (JFrame). Cechy charakterystyczne:
– niezależny od platformy wygląd
– muszą być dodawane do innych kontenerów
– dodatkowe możliwości programistyczne (np. dynamicznych zmian
właściwości takich jak możliwość zmiany rozmiaru, możliwość
maksymalizacji itp.)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Operacja zamknięcia okna może mieć różne skutki zdefiniowane za
pomocą następujących stałych:
• DO_NOTHING_ON_CLOSE
• HIDE_ON_CLOSE - operacja domyślna (chowa okno, ale nie
likwiduje go)
• DISPOSE_ON_CLOSE - usunięcie okna
• EXIT_ON_CLOSE - powoduje zamknięcie aplikacji
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – rozkłady
Rozkłady (Layouts)
Metody:
• pack() – wywoływana na rzecz kontenera; wywołuje metody układania
komponentów przez zarządców rozkładu (Layout Managers) dla
wszystkich kontenerów w hierarchii zawierania się komponentów w oknie
• revalidate() – wywoływana na rzecz zmienionego komponentu,
którego rozmiary uległy zmianie; jej wywołanie powoduje ponowne
ułożenie komponentów w kontenerze przez zarządcę rozkładu
• repaint() – wywoływana na rzecz zmienionego komponentu, którego
rozmiary uległy zmianie; uwidacznia zmiany wynikające z
wcześniejszego wywołania revalidate()
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – rozkłady
Menadżerowie rozkładu ingerują w rozkład komponentów w obszarze
Content Pane okna a nie w całym oknie.
Proste rozkłady:
• FlowLayout
• BorderLayout
• GridLayout
Złożone rozkłady:
• GridBagLayout – elastyczny ale trudny w użyciu
• CardLayout – rzadko się przydaje
• GroupLayout – stosowany w edytorach GUI
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – rozkłady
Najbardziej przydatne rozkłady z biblioteki Swing:
• BoxLayout – prosty i bardzo elastyczny
Bardzo przydatne rozkłady opracowane poza Swingiem:
• TableLayout
• MigLayout
Można albo pisać własne Layout Managery, albo wyłączyć je i
ustawiać kontrolki ręcznie:
kontener.setLayout(null);
setBounds(x,y,w,h), gdzie x, y - współrzędne położenia
komponentu, w,h - szerokość i wysokość.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – rozkłady
W celu zapewnienia atrakcyjnego wyglądu GUI w praktyce układa się
za pomocą jednych rozkładów panele zagnieżdżając je w sobie, a dopiero
w nich umieszcza się w różnych rozkładach kontrolki.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – wielowątkowość
Tworzenie i odwoływanie się do komponentów Swingu (odczytywanie
i zmiana ich właściwości) winno odbywać się wyłącznie w wątku obsługi
zdarzeń.
Wątek zdarzeń należy wykorzystać we własnej aplikacji za pomocą
metod zdefiniowanych w java.awt.EventQueue ale dostępnych również z
poziomu javax.swing.SwingUtilities:
• SwingUtilities.invokeLater() – kod implementacji interfejsu
Runnable zostanie przekazany do wykonania wątkowi obsługi zdarzeń, a
wykonanie bieżącego wątku będzie kontynuowane
• SwingUtilities.invokeAndWait() – j.w., ale wykonanie bieżącego
wątku zostanie wstrzymane do chwili wykonania przekazanego kodu
przez wątek obsługi zdarzeń
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – wielowątkowość
Przyjmuje się zasadę, że wszelkie działania na GUI (tworzenie
komponentów, dodawanie komponentów do kontenerów, ustalanie
właściwości komponentów wizualnych) winny być wykonywane w
wątku obsługi zdarzeń.
Możliwe jest też stosowanie osłabionej wersji powyższej zasady
Swingu - dopiero po realizacji komponentów - czyli spakowaniu i/lub
uwidocznieniu okna - wszelkie na nich działania muszą odbywać się w
wątku obsługi zdarzeń, jednak nie jest to dobra praktyka ze względu na
brak gwarancji poprawnego działania.
UWAGA: w przykładzie załączonym do poprzedniego wykładu
skorzystano oczywiście z zasady Swingu w poprawnej postaci.
Z kodu przekazanego do wątku obsługi zdarzeń nie wolno wywoływać
metody invokeAndWait(), gdyż zablokuje to GUI.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing - komponenty
Cechy wspólne komponentów Swing:
• są komponentami lekkimi o niezależnym od platformy systemowej wyglądzie
(ale zależnym od dobieranych przez programistę ustaleń - "Look and Feel")
• możemy ustalać czy mają być przezroczyste, czy nie,
• istnieje możliwość zewnętrznego ustalania ich preferowanych, maksymalnych
i minimalnych rozmiarów (metody setPreferredSize, setMaximumSize,
setMinimumSize), oraz ich wyrównania względem innych komponentów
(metody setAlignmentX, setAlignmentY)
• mogą mieć ramki o dowolnie ustalanej formie (klasa BorderFactory),
• mogą mieć podpowiedzi ( "dymki" pomocy - fly-over help, tooltips)
• mogą być uaktywniane z klawiatury (operowanie na GUI za pomocą
klawiatury, nie tylko myszki)
• mogą mieć przypisaną dodatkową informację (w postaci tablicy asocjacyjnej,
kojarzącej obiekty-klucze i obiekty-wartości)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing - komponenty
Przykład zawansowanych możliwości tworzenia ramek złożonych z
kilku:
comp.setBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.blue),
comp.getBorder());
Można tworzyć własne ramki implementując metody paintBorder() i
getBorderInsets() we własnej klasie dziedziczącej z AbstractBorder.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – komponenty
Podpowiedzi:
JButton b = new JButton("Commit");
b.setTollTipText("Zapisz zmiany w bazie danych");
Tekst podpowiedzi może być napisem HTML.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – komponenty
Ikony:
Mogą zostać pobrane metodą getImage() z pliku graficznego
zapisanego w jednym z następujących formatów: GIF, JPG/JPEG, PNG
lub mogą zostać narysowane metodą paintIcon().
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing - komponenty
Przyciski
Dostępne są następujące rodzaje:
• JButton
• JToggleButton (też nadklasa dla kolejnych dwóch)
• JCheckBox
• JradioButton
Do grupowania przycisków typu "radio" (a więc wzajemnie
wykluczających się zaznaczeń) służy klasa ButtonGroup.
Po stworzeniu obiektu tej klasy, za pomocą metody add dodajemy do
niego przyciski JRadioButton. Od tej chwili tylko jeden z dodanych
przycisków może być aktualnie "zaznaczony".
Uwaga: ButtonGroup nie jest kontenerem!
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – komponenty
Dla każdego rodzaju przycisku za pomocą metody
setMnemonic(int c);
możemy ustalić mnemonikę czyli literę (znak), który wciśnięty wraz z
klawiszem alt spowoduje "kliknięcie" w przycisk.
Znak ten jest podkreślony w tekście na przycisku.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – menu
Hierarchia klas menu pokazana została na następnym slajdzie
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – menu
Możliwości dodawania skrótów klawiszowych do menu:
• setMnemonic(int) – obsługuje pojedynczy klawisz skrótu
• setAccelerator(KeyStroke) – obsługuje sekwencje klawiszy
Istnieje też możliwość dodawania kleju pomiędzy elementy menu w
celu rozsuwania ich pozycji, np. przesunięcia pozycji Help w menu bar do
prawej strony. Można również modyfikować layout menu, gdyż jest ono
kontenerem(!).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Wszystkie okna w Swing, jako jedyny rodzaj komponentów są
komponentami ciężkimi (z wyjątkiem lekkiego JInternalFrame).
Struktura okna:
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Kontener layeredPane umożliwia operowanie warstwami
komponentów.
Są dwa rodzaje uporządkowania:
• warstw, głębokość których określa obiekt typu Integer (numer
warstwy). Im wyższy numer, tym warstwa bliższa przedniego planu
(Z-order), Np. komponent dodany do warstwy 1 będzie zasłaniany
przez komponent dodany do warstwy 2
• pozycji komponentów (na osi Z) umieszczonych w jednej warstwie;
tutaj porządek jest odwrotny: komponent o wyższej pozycji jest
przykrywany przez komponent o niższej pozycji
Można też używać własnych warstw i dodawać do nich komponenty.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Odniesienie do kontenera layeredPane okna frame możemy uzyskać poprzez: JLayeredPane lp = frame.getLayeredPane();
Dodanie komponentu comp do warstwy n (liczba całkowita):lp.add(comp, new Integer(n));
Dodanie komponentu comp do warstwy n na pozycji m (liczba całkowita): lp.add(comp, new Integer(n), m);
Oprócz tego dostępne są metody klasy JLayeredPane, które dynamicznie
zmieniają położenie komponentów w ramach warstwy i pomiędzy warstwami: lp.moveToFront(comp)
lp.moveToBack(comp);
lp.setLayer(comp, n);
lp.setLayer(comp, n, m);
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Szyba
Jest zawarta w rootPane i przykrywa cały rootPane. Domyślnie jest
niewidoczna. Można ją jednak uaktywnić poprzez uwidocznienie:
Component g = frame.getGlassPane();
g.setVisible(true);
Po uwidocznieniu oddziela ona nas od okna.
Operacje możliwe do wykonywania na szybie:
• przechwytywanie zdarzeń wejściowych (mysz i klawiatura)
• rysowanie
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Można też stworzyć własną szybę, co jest szczególnie użyteczne, gdy
na szybie chcemy coś rysować. Wtedy utworzoną przez nas szybę
podstawiamy na miejsce standardowej za pomocą metody:
setGlassPane()
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Okna wewnętrzne (JInternalFrame) są lekkimi komponentami o
funkcjonalności okien ramowych. Podstawowe różnice wobec zwykłych
okien ramowych (JFrame):
• niezależny od platformy wygląd,
• muszą być dodawane do innych kontenerów,
• dodatkowe możliwości programistyczne (np. dynamicznych zmian
właściwości takich jak możliwość zmiany rozmiaru, możliwość
maksymalizacji itp.).
Ponieważ okna wewnętrzne zawarte są zawsze w jakimś kontenerze, to
stanowią one okna na wirtualnym pulpicie (nie mogą "wyjść" poza
pulpit). Pulpitem (kontenerem zawierającym okna wewnętrzne) jest
zwykle obiekt typu JDesktopPane, choć może to być i jakiś inny
kontener.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – okna
Okna klasy JInternalFrame nie generują zdarzeń typu WindowEvent.
Zamiast tego dostępne są zdarzenia typu InternalFrameEvent, a do ich
obsługi służą metody z interfejsu InternalFrameListener
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – kontenery
Każdy komponent Swing jest jednocześnie kontenerem. Nie należy jednak
nadużywać możliwości traktowania wszystkich komponentów Swingu jako
kontenerów. Swing dostarcza bowiem lepszych sposobów grupowania komponentów
w wyspecjalizowanych panelach:
• JPanel - najprostszy panel, różniący się od panelu AWT tym, że jest J-
komponentem (ze wszystkimi, omawianymi wcześniej konsekwencjami)
• JSplitPane - panel składających się z dwóch rozdzielonych paskiem podziału
części, w których mogą być umieszczone dowolne komponenty (w tym oczywiście -
kontenery)
• JTabbedPane - panel z zakładkami. Każda z zakładek daje dostęp do innego
komponentu (zwykle kontenera) po kliknięciu w zakładkę wypełniającego cały panel,
• JScrollPane - panel przewijany, z suwakami; odpowiednik ScrollPane z AWT, ale
o rozbudowanych możliwościach,
• JToolBar - pasek narzędzi, zawierający dowolne komponenty (zwykle przyciski
obrazkowe)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – kontenery
JTabbedPane
Panel zakładkowy udostępnia zakładki (tekst, tekst i ikona lub sama
ikona, możliwe jest również ustalenie jako zakładki dowolnego
komponentu). Z każdą zakładką związany jest inny komponent, który po
kliknięciu w zakładkę wypełnia panel.
Zakładki mogą być ulokowane u góry, u dołu, po lewej lub po prawej
stronie panelu.
JScrollPane
Komponenty mogące mieć paski przewijania powinny zostać
umieszczone w kontenerze JScroll Pane, aby ich paski przewijania zostały
uwidocznione.
JScrollPane ma złożoną budowę - zarządza aż dziewięcioma
komponentami.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
JToolbar
Od zwykłych kontenerów JToolBar różni się tym, że:
• może być przesywany myszką i doczepiany do dowolnego brzegu
okna lub całkiem od okna odczepiony (właściwość "floatable")
• można do niego dodać separator za pomocą metody addSeparator,
• można do niego dodawać obiekty typu Action (metoda add(Action a))
• ma domyślny rozkład BoxLayout.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – akcje
Jeśli mamy kilka komponentów (np. przycisk na pasku narzędzi,
element menu rozwijalnego lub element menu kontekstowego), które
powinny mieć tę samą funkcjonalność, to możemy w łatwy sposób,
jednokrotnie, funkcjonalność tę zdefiniować i łatwo przypisać ją tym
komponentom.
Służą do tego obiekty implementujące interfejs Action.
Atrakcyjność obiektu-akcji polega na tym, iż po jego utworzeniu może
on być równolegle dodany:
• do paska narzędzi (klasa JToolBar ma metodę add(Action)),
• do menu rozwijalnego (klasa JMenu ma metodę add(Action)),
• do menu kontekstowego
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – akcje
Mapy akcji i mapy klawiaturowe są bardziej ogólnym mechanizmem
wiązania skrótów klawiszowych z akcjami (za pomocą nazw) niż
mechanizmy omówione wcześniej (KeyListener, mnemoniki,
akceleratory).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – akcje
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – akcje
Mapę klawiaturową J-komponentu comp można uzyskać za pomocą odwołania:InputMap imap = comp.getInputMap(int rodzaj);
gdzie:
rodzaj - rodzaj mapy:
WHEN_FOCUSED,
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
WHEN _IN_FOCUSED_WINDOW.
Mapę akcji komponentu comp można uzyskać poprzez:ActionMap amap = comp.getActionMap();
Można też użyć odpowiednich metod setInputMap(...) i setActionMap(...). do ustalania
map dla komponentów.
Mapowanie odbywa się za pomocą wywołań metody:
put(KeyStroke, Object)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – akcje
Aby uzyskać obiekt klasy KeyStroke, reprezentujący skrót
klawiaturowy stosujemy statyczmną metodę tej klasy:
KeyStroke getKeyStroke(String)
której argumentem jest napis, oznaczający skrót klawiaturowy, np.
"control D".
Wiązanie odbywa się za pomocą wywołań metody:
put(Object, Action)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – obieralny wygląd
W Swing można dynamicznie ustalać wygląd i zachowanie.
Zarządzaniem wyglądem komponentów zajmuje się klasa UIManager.
Można też korzystać z gotowych menadżerów wyglądu oferowanych poza
Swingiem, np. :
• JGoodies – elegancki
UIManager.setLookAndFeel(
"com.jgoodies.looks.plastic.PlasticXPLookAndFeel");
• Substance – bardzo elastyczny i konfigurowalnyUIManager.setLookAndFeel(new SubstanceLookAndFeel());
SubstanceLookAndFeel.setCurrentTheme(new SubstanceSteelBlueTheme());
• Nimbus – bardzo eleganckiUIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – integracja z pulpitem
Istnieje możliwość integrowania aplikacji desktopowej Java opartej o
Swing z pulpitami systemów operacyjnych. Rozwiązani te nie zostaną
jednak tu omówione.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – czynności długotrwałe
Czynności długotrwałe realizowane z poziomu GUI w Swing mogą
być długotrwałe. Ich normalne wykonanie w wątku obsługi zdarzeń
zablokowałoby możliwość korzystania z GUI na czas wykonania tych
czynności.
Długotrwałe czynności nie mogą być wykonywane w wątku obsługi
zdarzeń (Event Dispatching Thread - EDT).
Do rozwiązywania tych problemów służy klasa SwingWorker.
Klasę tę wykorzystuje się przez dziedziczenie z niej. Dostępne metody:
• doInBackground()
• execute()
• done()
• get()
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – czynności długotrwałe
Klasa ta pozwala również uzyskiwać wyniki pośrednie długotrwałych
operacji, co pozwala na aktualizowanie danych w GUI w celu wizualizacji
postępów w wykonywaniu długotrwałego zadnia.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Architektura Swinga jest oparta o wzorzec architektoniczny MVC
(Model-View-Controler).
Zastosowanie tego wzorca służy m.in. ułatwieniu wprowadzania zmian
do kodu źródłowego dzięki ograniczeniu zasięgu tych zmian.
W ramach tego wzorca:
• model - określa dane związane z komponentem lub stany komponentu,
• widok (view) - określa wizualną reprezentację danych lub stanów,
• sterownik (controller) - zapewnia interakcję użytkownika z widokiem i
wynikające stąd modyfikacje modelu.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
W implementacji Swinga wprowadzono jednak pewne dodatkowe
założenie ograniczające elastyczność podejścia oferowanego przez MVC,
mianowicie połączono widok z kontrolerem za pomocą delegacji
(delegacja jest prostym mechanizmem obiektowym polegającym na
przeniesieniu części zobowiązań z obiektu do obiektu w nim
agregowanego – innymi słowy delegowanie oznacza stosowanie relacji
agregacji). Obiekt ten to tzw. delegat UI.
Zatem w Swing odseparowano model od delegatów UI.
Wyróżnia się dwa typy modelu dla komponentów Swing:
• modele GUI - interfejsy definiujące wizualne stany komponentów, np.
przycisk wciśnięty lub zaznaczenie elementu na liście,
• modele danych - interfejsy reprezentujące dane takie jak np. wartość
komórki w tabeli lub elementu listy
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Dostęp do modelu w ramach komponentu Swing dają metody:
• getModel()
• setModel()
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
JList
Klasa ta implementuje oba interfejsy modelu: GUI i danych.
Do tej pory działaliśmy na tym komponencie statycznie jak na liście
(zamknięty zbiór danych). Jednak czasem potrzebne jest skorzystanie z
modelu danych:
• jeśli chcemy w sposób niestandardowy (nie sprowadzający się do
użycia tablic lub wektorów) określić zawartość listy - winniśmy stworzyć
własny model danych
• jeśli chcemy mieć listę dynamiczną tzn. zmieniającą swoją zawartość -
możemy stworzyć własny model lub posłużyć się modelem
implementowanym w klasie DefaultListModel
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Model danych dla listy jest określany przez interfejs ListModel,
abstrakcyjna klasa AbstractListModel implementuje ten interfejs,
pozostawiając do zdefiniowania w klasach pochodnych dwie ważne
metody:
• Object getElementAt(int i) - zwraca i-ty element modelu
(element listy)
• int getSize() - zwraca liczbę elementów listy
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Przykład powiązania modelu z kontrolerem:
AbstractListModel listModel =
new AbstractListModel() {
public Object getElementAt(int i) {}
int getSize() {}
}
Możliwości powiązania modelu z komponentem:
JList list = new JList();
list.setModel(listModel);
albo:
JList list = new JList(listModel);
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Komunikacja model-widok
Zasady:
• Wszelkie zmiany (które ew. będą uwidocznione w widoku) muszą być
dokonywane jako zmiany w modelu danych
• O każdej zmianie model musi powiadamiać zainteresowanych
słuchaczy, kreując odpowiednie zdarzenia za pomocą metod fire...;
zdarzenia te będą przekazywane do odpowiednich delegatów
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Komunikacja model-widok dla JList
Rodzaje modeli danych:
• model automatyczny, tworzony w konstruktorach, które nie mają
modelu jako argumentu
• model domyślny (DefaultListModel) – przygotowana klasa, która
ułatwia tworzenie dynamicznych list
• modele własne
Model automatyczny nie pozwala na automatyczne uwidacznianie
zmian modelu w widoku.
Oby uniknąć tego ograniczenia należy utworzyć własny model.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Zdarzenia zmian modelu należą do klasy ListDataEvent i mają
następujące charakterystyki:
• typ (zapytanie getType()): przedział indeksów dodany, przedział
indeksów usunięty, zmiana zawartości
• dolny indeks przedziału (zapytanie getIndex0())
• górny indeks przedziału (zapytanie getIndex1())
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Do nasłuchu zmian w modelu służy interfejs ListDataListener, który
udostępnia trzy metody:
intervalAdded(ListDataEvent e)
intervalRemoved(ListDataEvent e)
contentsChanged(ListDataEvent e)
Klasa AbstractListModel definiuje trzy zabezpieczone metody,
służące do powiadamiania słuchaczy o zmianach w modelu:
• protected void fireIntervalAdded(Object source, int index0, int index1)
• protected void fireIntervalRemoved(Object source, int index0, int index1)
• protected void fireContentsChanged(Object source, int index0, int index1)
Metody te generują zdarzenia ListDataEvent z odpowiednimi
charakterystykami i rozsyłają te zdarzenia do wszystkich
zarejestrowanych słuchaczy.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Przykład tworzenia własnego modelu:
Zbyt skomplikowany na slajdy, daje możliwość zrealizowania
szerokiego spektrum funkcjonalności, ale rzadko jest potrzebny.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Realizowanie własnego modelu jest dość kłopotliwe. Dlatego twórcy
Swinga wbudowali w tę bibliotekę klasę DefaultListModel.
Sposób korzystania:
DefaultListModel lm = new DefaultListModel();
JList list = new JList(lm);
lm.addElement(...)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Nasłuch zmian modelu
Istnieją dwa typy interfejsów nasłuchu:
• ChangeListener, który nasłuchuje zdarzeń typu ChangeEvent.
Można z niego jedynie uzyskać informację o źródle zmiany
(getSource), ale nie o jej charakterze – trzeba odpytywać model.
• wyspecjalizowane interfejsy, które obsługują zdarzenia zawierające
informacje o konkretnych zmianach modelu (wiele typów interfejsów
nasłuchu oraz zdarzeń, specyficznych dla konkretnych modeli).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
JComboBox
Klasa JComboBox ma dwie przyjemne właściwości:
• pozwala na selekcję elementów listy poprzez wciskanie klawiszy
oznaczających pierwsze litery napisów,
• oraz umożliwia dynamiczne zmiany zawartości listy bez
bezpośredniego użycia modelu danych z nią związanych.
Mimo to model może być nadal przydatny. Można go np. wykorzystać
do odsiewania duplikatów z listy.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Wykreślacze (Renderers)
Służą do rysowania komponentu, ale jedynie jako widok bez
funkcjonalności.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
JTable
Komponent ten należy do najbardziej rozbudowanych.
Prosty przykład:
Object[][] dane = {
{"Kowalski", "Jan", new Integer(30), new Boolean(true) },
{ Jankowski", "Jan", new Integer(20), new Boolean(false) },
.... };
Object[] nazwyKolumn = {
"Nazwisko", "Imię", "Wiek", "Urlop wykorzystany?"
};
JTable tab = new JTable(dane, nazwyKolumn);
JScrollPane sp = new JScrollPane(tab);
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Każda tabela jest związana z trzema modelami:
• modelem danych - obiektem klasy implementującej interfejs
TableModel,
• modelem kolumn - TableColumnModel,
• modelem selekcji - znany już interfejs ListSelectionModel.
Zróżnicowanie modeli związane jest m.in. z potrzebą zapewnienia
braku zgodności kolejności kolumn w modelu danych z ich kolejnością w
widoku.
Tabela może zawierać dowolne obiekty i wyświetlać w komórkach
dowolne komponenty.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Klasa TableColumn zawiera metody określające właściwości kolumn
tabeli. Z każdą kolumną - obiektem TableColumn - skojarzony jest:
• nagłówek,
• wykreślacz komórek (obiekt typu TableCellRenderer)
• edytor komórek (obiekt typu TableCellEditor)
• wykreślacz nagłówka.
Pewne typy danych mają ustalone domyślne wykreślacze i edytory.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
JTree
Klasa JTree zapewnia hierarchiczne obrazowanie danych w postaci
drzewa.
W drzewach - podobnie jak w tabelach - mamy do czynienia:
• z modelem danych (klasy implementujące interfejs TreeMedel;
domyślna implementacja DefaultTreeModel pozwala modyfikować
drzewo przez modyfikacje modelu danych)
• z modelem selekcji węzłów (TreeSelectionModel)
• z nasłuchem zdarzeń selekcji (TreeSelectionListener)
• z wykreślaczami komórek (TreeCellRenderer)
• z edytorami komórek (TreeCellEditor).
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Komponenty tekstowe
Są to najbardziej rozbudowane komponenty Swinga. Uważa się, że
pozwalają one na tworzenie dowolnie złożonych rozwiązań.
Na kolejnym slajdzie pokazano hierarchię tych komponentów.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVCW tej złożonej architekturze można wyróżnić:
• model danych - reprezentowany przez obiekty klasy implementujących interfejs Document;
model danych opisuje zawartość dokumentu
• widok - który zarządza uwidaczanianiem dokumentu i jego fragmentów (widoki są
produkowane przez podklasy klasy View; pośredniczą pomiędzy modelem danych a widokami
"niskiego poziomu" związanymi z delegatami UI)
• kontroler - edytor, który dostarcza możliwości edycyjnych oraz odczytu/zapisu dokumentów
z/do strumieni. Edytory są obiektami klas dziedziczących klasę EditorKit
• powiązania pomiędzy klawiszami i akcjami edycyjnymi; interfejs KeyMap wiąże klawisze
(obiekty typu KeyStroke) z obiektami typu Action; jest to alternatywny wobec ogólnego modelu
akcji klawiaturowych (ActionMap i InputMap, o których mowa była w wykładzie 11) sposób
tworzenia. modyfikacji i użycia klawiszy edycyjnych; model ogólny jest obecnie preferowany
• menedżer cofania (undo) i przywracania (redo) edycji (UndoManager), pozwalający łatwo
realizować właściwości undo-redo
• kursor tekstowy - realizowany przez interfejs Caret; może być dowolnie dostosowywany jeśli
chodzi o wygląd poprzez odpowiednią implementację tego interfejsu
• podświetlacze - realizowane przez interfejs Highliter; klasy implementujące ten interfejs
określają sposoby zaznaczania różnych fragmentów dokumentu
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Z komponentami tekstowymi wiążą się również nowe zdarzenia i
nowe interfejsy nasłuchu:
• DocumentListener umożliwia śledzenie i reagowanie na zmiany w
dokumencie (zdarzenie typu DocumentEvent)
• CaretListener pozwala śledzić zmiany pozycji kursora tekstowego
(CaretEvent)
• UndoableEditionListener umożliwia kompletowanie dokonanych
edycji (poprawek) i przygotowanie UndoManagera do ich cofania (a po
cofnięciu - przywracania)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Istnieje możliwość tworzenia GUI z plików zasobów (property files
lub XML), ale jest ona wspierana przez zewnętrzne narzędzia. Zaletą jest
mniej kodu po stronie GUI i możliwość skupienia się w nim na obsłudze
zdarzeń.
Przykład narzędzia działającego w ten sposób:
http://www.swixml.org/
Czy w NetBeans też tak się da?
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Architektura Swing jest zgodna z wzorcem architektonicznym (należy
odróżniać tę kategorię wzorców od wzorców projektowych) MVC
(Model-View_Controler). W ramach tego wzorca warstwa prezentacji
może być zależna od warstwy kontrolerów jak i od warstwy danych.
Jednocześnie warstwa kontrolerów zależy od warstwy danych. Innych
zależności w tym wzorcu nie ma.
Są jednak znane wzorce architektoniczne lepsze pod względem
możliwości wprowadzania, np. MVP (Model-View-Presenter) wolny od
zależności warstwy prezentacji od warstwy danych.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing – MVC
Testowanie
Wykorzystanie wzorca MVC nadaje nie tylko ramy implementacji ale
wprowadza też możliwości uporządkowania podejścia do testowania
oprogramowania. Można w ramach tego wzorca wykonywać następujące
testy:
• Testy jednostkowe
– Testy elementów warstwy danych (klas encyjnych – w UML
stereotyp <<entity>>)
– Testy elementów warstwy kontrolerów (klas kontrolerów – w
UML stereotyp <<control>>)
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
• Testy funkcjonalne
– Są to tylko i wyłącznie testy API warstwy kontrolerów
• Testy integracyjne - weryfikują one poprawność komunikacji
pomiędzy warstwami:
– Danych i kontrolerów
– Prezentacji i kontrolerów
– Prezentacji i danych
• Testy GUI – są to testy wykonywane na obiektach biblioteki Swing
Warto pamiętać, że testy te są zwykle wykonywane kolejnymi
kategoriami w takiej kolejności jak zostało to przedstawione powyżej ze
względu na zależności pomiędzy ich rodzajami i czas ich wykonania.
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
GUI w Swing
Narzędzia testujące GUI w Swing z poziomu Eclipse:
• FEST -Swing
• Jubula functional testing tools (wraz z GUI Dancer)
• UISpec4J
• Google Window Tester Pro GUI Tester
• Maveryx
Aktualny przegląd i charakterystyka niektórych narzędzi:
https://wiki.eclipse.org/Eclipse/Testing
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania
Koniec
dr inż. Piotr Zabawa Instytut Informatyki Wydział Fizyki, Matematyki i Informatyki
Zakład Inżynierii Oprogramowania