JAVA programowanie GUI (AWT i Swing)

Podobne dokumenty
Programowanie Multimediów. Programowanie Multimediów JAVA. programowanie GUI. (AWT i Swing) [1]

Programowanie Multimediów. Programowanie Multimediów JAVA. grafika w JAVA 2D API [1]

Rozdział 6 Grafika i multimedia w Javie

Java: otwórz okienko. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Programowanie obiektowe

Java Swing. Tomasz Mularczyk Luty 2005

Tworzenie elementów graficznych

Język JAVA podstawy. Wykład 5, część 4. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Programowanie obiektowe

Język JAVA podstawy. Wykład 5, część 2. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Kurs programowania. Wykład 6. Wojciech Macyna. 7 kwietnia 2016

Grafika i komunikacja człowiek komputer Laboratorium. Część 1: Wstęp do grafiki

Język JAVA podstawy. Wykład 5, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Programowanie zdarzeniowe

Java - interfejs graficzny

SWING. dr Jarosław Skaruz

Tworzenie i obsługa graficznego interfejsu uŝytkownika

Graphic User Interfaces pakiet Swing

Programowanie graficznego interfejsu użytkownika. Wykład 8. Maciej Wołoszyn 10 maja 2006

Kurs programowania. Wykład 4. Wojciech Macyna. 23 marca 2016

Język JAVA podstawy. wykład 2, część 2. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Materiał pomocniczy do kursu Podstawy programowania Autor: Grzegorz Góralski ggoralski.com

Podstawy Swing. Tomasz Borzyszkowski

Rysowanie prostych obiektów graficznych przy użyciu biblioteki AWT (Abstract Window Toolkit)

JAVA. Java jest wszechstronnym językiem programowania, zorientowanym. apletów oraz samodzielnych aplikacji.

Podstawy tworzenia aplikacji z wykorzystaniem języka Java ME ćwiczenia 2

Laboratorium z informatyki sem. III/ćw. 2 Wydział Transportu PW /19 MATERIAŁY POMOCNICZE DO ĆWICZENIA 2

Java niezbędnik programisty spotkanie nr 12. Graficzny interfejs użytkownika

Java SE Laboratorium nr 5. Temat: Obsługa zdarzeń

Programowanie graficznych interfejsów użytkownika

Dokumentacja do API Javy.

Programowanie w Javie Wykład 6 Okienka w Javie (AWT)

4. W konstruktorze klasy Grafika wywołaj metodę określającą rozmiary ramki oraz ustaw kolor tła metodą setbackground():

Multimedia JAVA. Historia

Java 2D. dr Jarosław Skaruz

Język Java. Rysowanie GUI Określanie wyglądu komponentów

Spis treści. 1 Aplet. 2 Od aplikacji do apletu. 1 Aplet 1. 2 Od aplikacji do apletu 1. 3 Budowa apletu 3. 4 Cykl życia apletu 4

Języki i metody programowania Java Obsługa zdarzeń - przykłady

Projektowanie obiektowe. Roman Simiński Wzorce projektowe Wybrane wzorce strukturalne

Applety Java. Applety są przykładem kodu Java wykonywanego po stronie klienta, ale bez ujawnionej (jak w przypadku skryptu) wersji źródłowej

Marcin Luckner Warsaw University of Technology Faculty of Mathematics and Information Science

Programowanie obiektowe

Operatory. Składnia. Typy proste. Znaki specjalne

Programowanie Obiektowe GUI

Informatyka i Ekonometria Programowanie komputerów Ćwiczenia Tworzenie aplikacji wykorzystaniem graficznego interfejsu użytkownika - Swing.

Język Java część 2 (przykładowa aplikacja)

Architektura interfejsu użytkownika

PARADYGMATY PROGRAMOWANIA Wykład 4

Aplikacje w środowisku Java

Podstawowe informacje o apletach

Grafika i komunikacja człowiek komputer Laboratorium. Część 2: Graphics

Obsługa zdarzeń. Wykład 4

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz

Programowanie obiektowe zastosowanie języka Java SE

Interfejsy w Java. Przetwarzanie równoległe. Wątki.

GLKit. Wykład 10. Programowanie aplikacji mobilnych na urządzenia Apple (IOS i ObjectiveC) #import "Fraction.h" #import <stdio.h>

JAVA. Strumienie wejścia i wyjścia. Pliki - zapis i odczyt

Java jako język programowania

Programowanie w JAVA Lab. 5 - Wątki. 1. Wykorzystując metodę Monte Carlo narysować wykres funkcji oraz obliczyć całkę: 7 x ) xy, 8,8

- Narzędzie Windows Forms. - Przykładowe aplikacje. Wyższa Metody Szkoła programowania Techniczno Ekonomiczna 1 w Świdnicy

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Sposoby tworzenia projektu zawierającego aplet w środowisku NetBeans. Metody zabezpieczenia komputera użytkownika przed działaniem apletu.

Kontenery i komponenty graficzne

SWING c.d. przydatne narzędzia: JFileChooser, JOptionPane. drag'n drop, menu kontekstowe.

Podstawy Języka Java

Język JAVA podstawy. Wykład 5, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Programowanie Multimediów. Programowanie Multimediów JAVA. wprowadzenie do programowania (3/3) [1]

Marcin Luckner Warsaw University of Technology Faculty of Mathematics and Information Science

Programowanie obiektowe

Programowanie obiektowe

Wykład 12: Obsługa Zdarzeń

Aplikacja wielowątkowa prosty komunikator

Języki i metody programowania Java. Wykład 2 (część 2)

Język JAVA podstawy. wykład 2, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Henryk Budzisz. materiały przygotowane w ramach projektu ZPORR nr POKL /08-00

Microsoft Visual C : praktyczne przykłady / Mariusz Owczarek. Gliwice, cop Spis treści

GUI - projektowanie interfejsów cz. II

Programowanie obiektowe

Wizualne systemy programowania. Wykład 11 Grafika. dr Artur Bartoszewski -Wizualne systemy programowania, sem. III- WYKŁAD

1 Atrybuty i metody klasowe

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Klasy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 13

Interfejsy i klasy wewnętrzne

Grafika i komunikacja człowiek komputer Laboratorium. Część 3: Tekst, czcionki, kolory

Obiektowe programowanie rozproszone Java RMI. Krzysztof Banaś Systemy rozproszone 1

Aplikacje w środowisku Java

Języki i metody programowania Java Lab2 podejście obiektowe

Interaktywne aplety obsługa zdarzeń, uruchamianie apletu przez przeglądarkę lub maszynę wirtualną Javy. Tworzenie łącz w apletach

STWORZENIE PRZYKŁADOWEJ

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

JAVA Materiały do laboratorium III wersja niezaawansowana Marcin Borkowski WSEiZ czerwiec 2006

Podstawowe części projektu w Javie

1. Co będzie wynikiem wykonania poniŝszych instrukcji? g2d.gettransform().scale(1, -1); g2d.gettransform().translate(4, -8); g2d.drawline(4, 0, 4, 4);

Wywoływanie metod zdalnych

Wykład 7: Pakiety i Interfejsy

Informatyka I. Interfejs GUI wysokiego poziomu. Biblioteka Swing. Programowanie zdarzeniowe. Politechnika Warszawska Wydział Transportu 2018

Programowanie w Javie

Fragmenty są wspierane od Androida 1.6

Builder (budowniczy) Cel: Przykład:

Transkrypt:

JAVA programowanie GUI (AWT i Swing) [1]

Wprowadzenie Pierwotnym GUI dla Javy był AWT (Abstract Window Toolkit) wg legendy powstał w miesiąc... Swing dodano dopiero w wersji Javy 1.2 (przełom 1997/98) Dlaczego skonstruowano kolejny sposób tworzenia interfejsów? [2]

Dlaczego nie AWT? Główny powód: niezadowolenie osób tworzących w Javie z istniejącego rozwiązania Wygląd interfejsów stworzonych przy pomocy AWT zależało od systemu operacyjnego AWT oferowało słabe wsparcie dla rysowania na ekranie oraz nie zapewniało kompatybilności operacji Drag and Drop pod kontrolą różnych systemów operacyjnych [3]

AWT a Swing AWT: Wygląd kontrolek specyficzny dla każdego systemu operacyjnego Swing: Wygląd kontrolek niezależny od systemu operacyjnego Schematy wyglądu (look and feel) Rozbudowane wsparcie dla rysowania 2D [4]

AWT a Swing AWT: Korzysta z wywołań funkcji systemowych przy tworzeniu i zarządzaniu wyglądem aplikacji Generalnie szybki, choć szybkość działania zależy od systemu operacyjnego Swing: W całości napisany w Javie Nieco wolniejszy, ale mniejsze różnice w prędkości pomiędzy platformami [5]

AWT i Swing AWT i Swing zawierają 2 podstawowe klasy: Component : metody dostępu do komponentów graficznych oraz metody do zmiany ich właściwości, Container : podklasa Component dostarczająca tzw. pojemniki, czyli obiekty grupujące [6]

[7]

[8]

[9]

[10]

Rozmieszczanie elementów na ekranie Kontrolą rozmieszczenia obiektów na ekranie zajmuje się Container. Do dyspozycji jest kilka klas. 1. BorderLayout (domyślny) 2. FlowLayout 3. GridLayout 4. GridBagLayout 5. null 6. BoxLayout [11]

Rozmieszczanie elementów na ekranie import java.awt.*; import java.applet.applet; public class buttondir extends Applet { public void init() { setlayout(new BorderLayout()); add(new Button("North"), BorderLayout.NORTH); add(new Button("South"), BorderLayout.SOUTH); add(new Button("East"), BorderLayout.EAST); add(new Button("West"), BorderLayout.WEST); add(new Button("Center"), BorderLayout.CENTER); } } [12]

Rozmieszczanie elementów na ekranie import java.awt.*; import java.applet.applet; public class mybuttons extends Applet { Button button1, button2, button3; public void init() { button1 = new Button("Ok"); button2 = new Button("Open"); button3 = new Button("Close"); add(button1); add(button2); add(button3); } } [13]

Rozmieszczanie elementów na ekranie import java.awt.*; import java.applet.applet; public class ButtonGrid extends Applet { public void init() { setlayout(new GridLayout(3,2)); add(new Button("1")); add(new Button("2")); add(new Button("3")); add(new Button("4")); add(new Button("5")); add(new Button("6")); } } [14]

Rozmieszczanie elementów na ekranie private javax.swing.jlabel getivjjlabel(){ if(ivjjlabel == null) { ivjjlabel = new javax.swing.jlabel(); ivjjlabel.setbounds(59, 10, 38, 15); ivjjlabel.settext("jlabel"); } return ivjjlabel; } [15]

Model View - Controller INPUT PROCESSING OUTPUT Podejście klasyczne CONTROLLER MODEL VIEW Podejście MVC [16]

Dlaczego MVC? Podejście po raz pierwszy wykorzystano w Smalltalku 80 Kontrolery, model i widoki traktowane jako oddzielne elementy Zmiany modelu natychmiast odzwierciedlane w widokach [17]

Model View - Controller VIEW CONTROLLER VIEW CONTROLLER MODEL VIEW CONTROLLER VIEW [18]

Założenia MVC... Wszystkie komponenty w systemie muszą dać się określić jako kontroler, model, widok bądź część któregoś z nich Połączenie model <-> widok jest realizowane dynamicznie w czasie działania programu, a nie w czasie kompilacji Jeżeli zaprojektujemy w MVC każdy komponent, to łatwe będzie ich łączenie w spójny projekt [19]

Założenia MVC... Usuwanie bądź przebudowa komponentu nie pociąga za sobą potrzeby ingerencji w cały system Model nie wie, jakie są jego kontrolery, nie zna także korzystających z niego widoków sam system zajmuje się ich spójnym połączeniem Kontrolery i Widoki znają skojarzony z nimi Model [20]

Przykład zastosowania MVC Gra komputerowa 3D shoot 'em up AKCJA: RUCH AKCJA: STRZAŁ AKCJA: OTWIERANIE DRZWI MODEL(e) ŚWIATA, OBIEKTÓW, POSTACI WIDOK: FPP WIDOK: Z GÓRY WIDOK: OD STRONY PRZECIWNIKA [21]

Java a MVC... Java oferuje wsparcie dla MVC poprzez dwie klasy: Obserwator (Observer) obiekt, który chce być powiadamiany o zmianach w innym obiekcie Obserwowany (Observable) każdy obiekt, którego zmiana stanu może zainteresować inny obiekt [22]

Swing a MVC observable MODEL CONTROLLER VIEW GUI observer [23]

Przykład (JButton) Model przechowuje stan, pozwala na jego modyfikację i odczytywanie. Dodatkowo pozwala dodawać/usuwać słuchaczy(listeners). Widok i kontroler zajmują się wyświetlaniem stanu i przycisku na ekranie. Tutaj także pamiętamy, w którym miejscu na ekranie znajduje się przycisk. Ta część zajmuje się również obsługą zdarzeń AWT. [24]

Zdarzenia W modelu, z którego korzysta Swing, akcje podejmowane są w odpowiedzi na zajście konkretnych zdarzeń. Aby powiązać zdarzenie z określoną akcją, każdej kontrolce musimy przyporządkować specjalną klasę, która będzie reagowała na zajście tego zdarzenia. Tę klasę nazywamy słuchaczem. [25]

Zdarzenia W modelu tym występuje strona wyzwalająca (trigger) zdarzenie i nasłuchująca (listener), czy zdarzenie zaszło. Aby móc nasłuchiwać, trzeba się najpierw zarejestrować u wyzwalającego i tym samym wyrazić zainteresowanie danym zestawem zdarzeń. Wówczas wyzwalający w razie zajścia zdarzenia będzie mógł wywołać na rzecz nasłuchującego metodę odpowiadającą zdarzeniu. Zestaw metod opowiadających zdarzeniom jest określony przez interfejs. Gdy korzysta się z wbudowanego systemu zdarzeń, wystarczy napisać stronę nasłuchującą, zwaną nasłuchiwaczem. Jest to klasa implementująca interfejs przeznaczony dla danego zestawu zdarzeń. [26]

Zdarzenia [27]

Zdarzenia import java.awt.event.actionlistener; import java.awt.event.actionevent; Większość komponentów reaguje na działania użytkownika wyzwoleniem zdarzenia akcji. Zdarzenie akcji jest reprezentowane przez obiekt ActionEvent, od którego można pozyskać informację na temat zdarzenia. Interfejs odpowiadający zdarzeniom akcji to ActionListener z metodą actionperformed. Aby obsługiwać działania użytkownika należy na komponencie zarejestrować metodą addactionlistener nasłuchiwacza, czyli instancję implementującą ten interfejs. [28]

Zdarzenia class ObslugaPrzycisku implements ActionListener { OblsugaPrzycisku() { JButton przycisk = new JButton("Naciśnij mnie"); przycisk.addactionlistener(this); } public void actionperformed(actionevent e) { System.out.println("I po co naciskasz?"); } } [29]

Zdarzenia - mysz Obsługa myszy opiera się na standardowym modelu zdarzeń. Interakcje użytkownika z myszą podzielono między kilka interfejsów: 1. podstawowy MouseListener 2. śledzący ruch wskaźnika MouseMotionListener 3. obejmujący oba powyższe MouseInputListener 4. śledzący obroty kulki myszy MouseWheelListener [30]

Zdarzenia - mysz Podstawowy interfejs import java.awt.event.mouselistener; import java.awt.event.mouseevent; MouseListener dostarcza następujące metody: [31] * kliknięcie myszą void mouseclicked(mouseevent e) * naciśnięcie przycisku myszy void mousepressed(mouseevent e) * zwolnienie przycisku myszy void mousereleased(mouseevent e) * wejście myszy w obszar śledzenia void mouseentered(mouseevent e) * wyjście myszy z obszaru śledzenia void mouseexited(mouseevent

Zdarzenia - mysz class ObsługaMyszy impelements MouseListener { ObsługaMyszy() { addmouselistener(this); // rejestracja zainteresowania zdarzeniami } } public void mouseclicked(mouseevent e) { System.out.println("Kliknięto " + e.getclickcount() + "razy"); System.out.println("w punkcie: (" + e.getx() + "," + e.gety() + ")"); } [32]

Wtyczki GUI (look and feel) Schematy wyglądu dostarczane wraz ze Swingiem: GTKLookAndFeel (Linux z GTK) MetalLookAndFeel (typowy dla Javy) MotifLookAndFeel WindowsLookAndFeel (typowy dla Windows) [33] DefaultLookAndFeel

Wybór look and feel Jeśli aplikacja nie określi swojego LookAndFeel, zostanie użyty domyślny LookAndFeel Javy. [34] Wybór lookandfeel powinien wystąpić jako pierwszy w programie. Aby aplikacja przypominała wyglądem pozostałe, należy wybrać LookAndFeel zależny od platformy. Metoda wyboru rzuca różne wyjątki, którymi trzeba się zająć: try { UIManager.setLookAndFeel(UIManager.getSystemLookAnd FeelClassName()); } catch (Exception e) { System.err.println("Nie można wybrać LookAndFeel");

Wybór look and feel UIManager.setLookAndFeel( "com.sun.java.swing.plaf.gtk.gtklookandfeel"); "com.sun.java.swing.plaf.gtk.gtklookandfeel" "javax.swing.plaf.metal.metallookandfeel" "com.sun.java.swing.plaf.windows.windowslookandfeel" "com.sun.java.swing.plaf.motif.motiflookandfeel" [35]

Jigloo [36]

JForm Designer [37]

Podsumowanie Swing rozszerza AWT i przerasta go w wielu względach Wygląd aplikacji napisanych przy użyciu Swinga jest taki, jakiego sobie zażyczymy na każdej platformie Swing został zaprojektowany z uwzględnieniem architektury Model-View-Controller Dzięki zastosowaniu anonimowych słuchaczy pisanie kodu obsługującego zdarzenia jest szybkie [38]

JAVA grafika w JAVA 2D API [39]

Wprowadzenie Java2D API w sposób znaczny rozszerza możliwości graficzne AWT. Po pierwsze umożliwia zarządzanie i rysowanie elementów graficznych o współrzędnych zmiennoprzecinkowych (float i double). Własność ta jest niezwykle przydatna dla różnych aplikacji m.in.: dla aplikacji w medycynie (wymiarowanie, planowanie terapii, projektowanie implantów, itp.), grafice inżynierskiej, symulacji procesów fizycznych Itp... Ta podstawowa zmiana podejścia do rysowania obiektów graficznych i geometrycznych powoduje powstanie, nowych, licznych klas i metod. [40]

Wprowadzenie W sposób szczególny należy wyróżnić tutaj sposób rysowania nowych elementów. Odbywa się to poprzez zastosowanie jednej metody: Graphics2D g2; g2.draw(shape s); [41]

Wprowadzenie Metoda draw umożliwia narysowanie dowolnego obiektu implementującego interfejs Shape (kształt). Przykładowo narysowanie linii o współrzędnych typu float można wykonać w następujący sposób: Line2D linia = new Line2D.Float(20.0f, 10.0f, 100.0f, 10.0f); g2.draw(linia); Line2D.Float(20.0f, 10.0f, 100.0f, 10.0f); g2.draw(linia); [42]

Klasa Line2D implementuje interfejs Shape. Java2D wprowadza liczne klasy w ramach pakietu java.awt.geom, np: Arc2D.Double Arc2D.Float CubicCurve2D.Double CubicCurve2D.Float Dimension2D Ellipse2D.Double Ellipse2D.Float GeneralPath Line2D Line2D.Double Line2D.Float Point2D Point2D.Double Point2D.Float QuadCurve2D.Double QuadCurve2D.Float Rectangle2D Rectangle2D.Double Rectangle2D.Float RoundRectangle2D.Double RoundRectangle2D.Float [43]

Charakterystyka JAVY W celu wykorzystania możliwości Java2D należy skonstruować obiekt graficzny typu Graphics2D. Ponieważ Graphics2D rozszerza klasę Graphics, to konstrukcja obiektu typu Graphics2D polega na rzutowaniu: Graphics2D g2 = (Graphics2D) g; gdzie g jest obiektem graficznym otrzymywanym dzięki AWT. Uwaga! Argumentem metody paint komponentów jest obiekt klasy Graphics a nie Graphics2D. [44]

Charakterystyka JAVY Dodatkowe klasy w AWT wspomagające grafikę to BasicStroke oraz TexturePaint. Pierwsza z nich umożliwia stworzenie właściwości rysowanego obiektu takich jak np.: szerokość linii, typ linii. Przykładowo ustawienie szerokości linii na 12 punktów odbywać się może poprzez zastosowanie następującego kodu: grubalinia = new BasicStroke(12.0f); g2.setstroke(grubalinia); Klasa TexturePaint umożliwia wypełnienie danego kształtu (Shape) określoną teksturą. [45]

TexturePaint public void paint(graphics g) { } Graphics2D g2 = (Graphics2D) g; BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); Graphics2D big = bi.creategraphics(); big.setcolor(color.blue); big.fillrect(0, 0, 5, 5); big.setcolor(color.lightgray); big.filloval(0, 0, 5, 5); Rectangle r = new Rectangle(0, 0, 5, 5); g2.setpaint(new TexturePaint(bi, r)); Rectangle rect = new Rectangle(5,5,200,200); g2.fill(rect); [46]

GradientPaint int x = 5; int y = 7; GradientPaint redtowhite = new GradientPaint(x, y, Color.red, 200, y,color.blue); g2.setpaint(redtowhite); g2.fill(new RoundRectangle2D.Double(x, y, 200, 200, 10, 10)); g2.setpaint(color.black); g2.drawstring("filled RoundRectangle2D", x, 250); [47]

Podstawowe możliwości graficzne [48]

GeneralPath GeneralPath oddshape = new GeneralPath();... public GeneralPath createpath(int x, int y) { x2 = x; y2 = y; oddshape.moveto(x, y); x -= 100; oddshape.lineto(x, y); y += 50; oddshape.lineto(x, y); x += 100; oddshape.lineto(x, y); x += 10; y -= 10; x1 = x - 20; y1 = y - 20; oddshape.curveto(x, y, x1, y1, x2, y2); return oddshape; } [49]

Do dodatkowych zalet grafiki w Java2D należy zaliczyć m. in.: sterowanie jakością grafiki (np. antyaliasing, interpolacje) sterowanie przekształceniami geometrycznymi (przekształcenia affiniczne - klasa AffineTransform), sterowanie przeźroczystością elementów graficznych, bogate narzędzia do zarządzania czcionkami i rysowania tekstu, narzędzia do drukowania grafiki. [50]

[51] Przykładowa aplikacja ukazująca proste elementy grafiki w Java2D Rysunki2.java: import java.awt.event.*; import java.awt.geom.*; import java.awt.*; public class Rysunki2 extends Frame { Rysunki2 () { super ("Rysunki2"); setsize(200, 220); } public void paint (Graphics g) { Graphics2D g2 = (Graphics2D) g; Line2D linia = new Line2D.Float(20.0f, 20.0f, 180.0f, 20.0f); g2.draw(linia); BasicStroke grubalinia = new BasicStroke(6.0f); g2.setstroke(grubalinia); g2.setcolor(color.red); Line2D linia2 = new Line2D.Float(20.0f, 180.0f, 180.0f, 180.0f); g2.draw(linia2); g2.drawstring ("Test grafiki",50, 100); g2.setcolor(color.black); } public static void main (String [] args) { Frame f = new Rysunki2 (); f.addwindowlistener(new WindowAdapter(){ public void windowclosing(windowevent e){ System.out.println("Dziekujemy za prace z programem..."); System.exit(0); } }); f.setvisible(true); } } // koniec public class Rysunki2 extends Frame

Obrazy Począwszy od pierwszych wersji w ramach AWT poprzez Java2D a skończywszy na najnowszej JAI (Java Advanced Imaging API - bardziej elastyczne definicje obrazów, bogate biblioteki narzędzi np. DFT) język JAVA dostarcza wiele narzędzi do tworzenia profesjonalnych systemów syntezy, przetwarzania, analizy i prezentacji obrazów. AWT Java2D JAI [52]

Obrazy W początkowych wersjach bibliotek graficznych Javy podstawą pracy z obrazami była klasa java.awt.image. Obiekty tej abstrakcyjnej klasy nadrzędnej uzyskiwane są w sposób zależny od urządzeń. Podstawowa metoda zwracająca obiekt typu Image (klasa Image jest abstrakcyjna), często wykorzystywana w programach tworzonych w Javie to getimage(). Metoda ta dla aplikacji jest związana z klasą Toolkit, natomiast dla appletów z klasą Applet. [53]

Przykłady Wywołanie metody getimage polega albo na podaniu ścieżki dostępu (jako String) lub lokalizatora URL do obrazu przechowywanego w formacie GIF lub JPEG. Przykładowo: Image obraz = Toolkit.getDefaultToolkit.getImage("pic.gif"); - zwraca obiekt obraz na podstawie obrazu przechowywanego w pliku pic.gif w bieżącej ścieżce dostępu Image obraz = Toolkit.getDefaultToolkit.getImage(new URL("http://www.wi.ps.pl/~user99/pic.gif"); - zwraca obiekt obraz na podstawie obrazu przechowywanego w pliku pic.gif na serwerze www.wi.ps.pl w danych podkatalogach. [54]

createimage Inną metodą uzyskania obiektu Image jest stworzenie obrazu poprzez wykorzystanie metody createimage(). Aby uzyskać obiekt typu Image za pomocą tej metody jako argument należy podać element implementujący interfejs ImageProducer. Obiekt będący instancją klasy implementującej ten interfejs jest odpowiedzialny za stworzenie (produkcję) obrazu jaki jest związany z obiektem typu Image. ImageProducer CreateImage Image [55]

ImageProducer Przykładowo w poprzednich metodach getimage() obiekt typu Image jest często zwracany wcześniej niż stworzony zostanie (np. załadowany z sieci) obraz. Wówczas metody odwołujące się do obiektu Image zwrócą błąd. Dlatego obiekt typu ImageProducer informuje klientów (obserwatorów) o zakończonym procesie tworzenia obrazu związanego z obiektem typu Image. [56]

Klienci - ImageObserver Klientów stanowią obiekty klas implementujących interfejs ImageObserver, których zachowanie jest ukazane poprzez jedyną metodę imageupdate(). Metoda ta zgodnie z informacją od obiektu ImageProducer żąda odrysowania elementu (np. komponentu graficznego jak np. panel, applet, itd. - java.awt.component implementuje interfejs ImageObserver). W czasie gdy ImageProducer wysyła informację o stanie do obiektu ImageObserver wysyła również dane do konsumenta czyli obiektu będącego wystąpieniem klasy implementującej interfejs ImageConsumer. [57]

ImageConsumer Przykładowe klasy implementujące interfejs ImageConsumer to java.awt.image.imagefilter oraz java.awt.image.pixelgrabber. Ponieważ do obiektu ImageConsumer dostarczane są wszystkie informacje związane z tworzonym obrazem (wymiary, piksele, model koloru) obiekt ten może za pomocą swoich metod wykonać wiele operacji na danych. Przykładowo obiekty klasy ImageFilter umożliwiają wycinanie próbek, filtrację kolorów, itp. natomiast obiekty klasy PixelGrabber umożliwiają pozyskanie części lub wszystkich próbkek z obrazu. [58]

PixelGrabber PixelGrabber pgobj = new PixelGrabber(rawImage, 0, 0, rawwidth, rawheight, pix,0,rawwidth); // --------------------------------------------- if(pgobj.grabpixels() && ((pgobj.getstatus() & ImageObserver.ALLBITS)!= 0)) { for(int cnt = 0; cnt<(rawwidth*rawheight);cnt++) { pix[cnt] = pix[cnt] & 0xC000FFFF; } } [59]

createimage Powracając do metody createimage(), której argumentem jest obiekt ImageProducer, umożliwia ona stworzenie (generację) obrazu na podstawie posiadanych danych. Konieczne jest jednak stworzenie obiektu typu ImageProducer, będącego argumentem tej metody. W tym celu wykorzystuje się klasę implementującą interfejs ImageProducer MemoryImageSource. Klasa ta dostarcza szereg konstruktorów, którym podaje się: typ modelu kolorów (ColorModel) lub wykorzystuje się domyślny RGB, rozmiar tworzonego obrazu, wartości pikseli. [60]

W następujący sposób można wygenerować własny obiekt typu Image: Obraz.java: import java.awt.event.*; import java.awt.image.*; import java.awt.*; public class Obraz extends Frame { Image ob; Obraz () { super ("Obraz"); setsize(200, 220); ob=stworzobraz(); } public Image stworzobraz(){ int w = 100; //szerokość obrazu int h = 100; //wysokość obrazu int pix[] = new int[w * h]; //tablica wartości próbek int index = 0; //generacja przykładowego obrazu for (int y = 0; y < h; y++) { int red = (y * 255) / (h - 1); for (int x = 0; x < w; x++) { int blue = (x * 255) / (w - 1); pix[index++] = (255 << 24) (red << 16) blue; } } Image img = createimage(new MemoryImageSource(w, h, pix, 0, w)); //tworzony jest obraz w RGB o szerokości w, wysokości h, //na podstawie tablicy próbek pix, bez przesunięcia w tej tablicy z w elementami w linii return img; } public void paint (Graphics g) { g.drawimage(ob,50,50,this); } public static void main (String [] args) { Frame f = new Obraz (); f.addwindowlistener(new WindowAdapter(){ public void windowclosing(windowevent e){ System.out.println("Dziekujemy za prace z programem..."); System.exit(0); } }); f.setvisible(true); } }//koniec public class Obraz extends Frame [61]

Mając obiekt typu Image można obraz z nim związany wyświetlić (narysować). W tym celu należy wykorzystać jedną z metod drawimage(). W najprostszej metodzie drawimage() podając jako argument obiekt typu Image, współrzędne x,y oraz obserwatora (ImageObserver, często w ciele klasy komponentu, w którym się rysuje odwołanie do obserwatora jest wskazaniem aktualnego obiektu komponentu - this) możemy wyświetlić obrazu w dozwolonym do tego elemencie. Inna wersja metody drawimage() umożliwia skalowanie wyświetlanego obrazu poprzez podanie dodatkowych argumentów: szerokość (width) i wysokość (height). [62]

Oprócz poznanych do tej pory operacji związanych z obrazami (stworzenie obiektu Image, filtracja danych, wyświetlenie i skalowanie) często wykorzystuje się dwie z kilku istniejących metod klasy Image, a mianowicie Image.getWidth() oraz Image.getHeight(). Metody te umożliwiają poznanie wymiarów obrazu, co jest często niezwykle istotne z punktu widzenia ich wyświetlania i przetwarzania. [63]

Potok przetwarzania obrazu w JAVIE: [64]

Java2D API rozszerza a zarazem zmienia koncepcję pracy z obrazami w Javie. Podstawową klasą jest w tej koncepcji klasa BufferedImage, będącą rozszerzeniem klasy Image z dostępnym buforem danych. [65]

Obiekt BufferedImage może być stworzony bezpośrednio w pamięci i użyty do przechowywania i przetwarzania danych obrazu uzyskanego z pliku lub poprzez URL. Obraz BufferedImage może być wyświetlony poprzez użycie obiektów klasy Graphics2D. Obiekt BufferedImage zawiera dwa istotne obiekty: obiekt danych - Raster oraz model kolorów ColorModel. Klasa Raster umożliwia zarządzanie danymi obrazu. Na obiekt tej klasy składają się obiekty DataBuffer oraz SampleModel. DataBuffer stanowi macierz wartości próbek obrazu, natomiast SampleModel określa sposób interpretacji tych próbek. [66]

Przykładowo dla danego piksela próbki (RGB) mogą być przechowywane w trzech różnych macierzach (banded interleaved) lub w jednej macierzy w formie przeplatanych próbek (pixel interleaved) dla różnych komponentów (R1,G1,B1,R2,G2,B2,...). Rolą SampleModel jest określenie jakiej formy użyto do zapisu danych w macierzach. Najczęściej nie tworzy się bezpośrednio obiektu Raster lecz wykorzystuje się efekt działania obiektu BufferedImage, który rozbija Image na Raster oraz ColorModel. Niemniej istnieje możliwość stworzenia obiektu Raster poprzez stworzenie obiektu WritableRaster i podaniu go jako argumentu w jednym z konstruktorów klasy BufferedImage. [67]

BufferedImage przykład URL url =... Image img = gettoolkit().getimage(url); try { //pętla w której czekamy na skonczenie produkcji obrazu dla obiektu img MediaTracker mt = new MediaTracker(this); mt.addimage(img, 0); mt.waitforid(0); } catch (Exception e) {} int iw = img.getwidth(this); int ih = img.getheight(this); BufferedImage bi = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB); //tworzymy obiekt BufferedImage Graphics2D g2 = bi.creategraphics(); //określamy kontekst graficzny [68] dla obiektu

BufferedImage przykład public void paint(graphics g) { if (getsize().width <= 0 getsize().height <= 0) return; Graphics2D g2 = (Graphics2D) g; if (bi!= null && isshowing()) { g2.drawimage(bi, 0, 0, this); } } [69]

BufferedImage predefiniowane typy TYPE_3BYTE_BGR TYPE_4BYTE_ABGR TYPE_4BYTE_ABGR_PRE TYPE_BYTE_BINARY TYPE_BYTE_GRAY TYPE_BYTE_INDEXED TYPE_CUSTOM TYPE_INT_ARGB_PRE TYPE_INT_ARGB TYPE_INT_BGR TYPE_INT_RGB TYPE_USHORT_555_RGB [70] TYPE_USHORT_565_RGB

Przetwarzanie obrazu w oparciu o BufferedImage Dla tak stworzonego obiektu BufferedImage można następnie przeprowadzić liczne korekcje graficzne, dodać elementy graficzne, zastosować metody przetwarzania obrazu oraz wyświetlić obraz. Wyświetlenie obrazu obiektu BufferedImage odbywa się poprzez wykorzystanie metod drawimage() zdefiniowanych dla klasy Graphics2D (np. g2.drawimage(bi,null,null);). [71]

Przetwarzanie obrazu w oparciu o BufferedImage Korekcje graficzne i dodawanie elementów graficznych polega na rysowaniu w stworzonym kontekście graficznym dla obiektu BufferedImage. Przetwarzanie obrazu odbywa się głównie poprzez wykorzystanie klas implementujących interfejs BufferedImageOp a mianowicie: AffineTransformOp, BandCombineOp, ColorConvertOp, ConvolveOp, LookupOp, RescaleOp. [72]

Filtracja obrazu Do najczęściej wykorzystywanych operacji należą: - przekształcenia geometryczne sztywne (affiniczne) - aplikacja AffineTransformOp - oraz operacje splotu - ConvolveOp Te ostatnie wykorzystuje się do tworzenia filtrów cyfrowych, za pomocą których można zmieniać jakość obrazu oraz wykrywać elementy obrazu jak np. linie, punkty, itp. [73]

Filtracja obrazu Poniższy przykład ukazuje możliwość realizacji filtra cyfrowego oraz przykładową operację skalowania. float[] SHARPEN3x3_3 = { BufferedImage bi=... 0.f, -1.f, 0.f, //maska filtru cyfrowego -1.f, 5.f, -1.f, 0.f, -1.f, 0.f}; AffineTransform at = new AffineTransform(); at.scale(2.0, 2.0); //określenie operacji geometrycznej-skalowanie wsp. 2 BufferedImageOp biop = null; BufferedImage bimg = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB); // tworzymy nowy bufor Kernel kernel = new Kernel(3,3,SHARPEN3x3_3); //tworzymy kernel - jądro splotu ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); //definiujemy operację splotu z przepisywaniem wartości krawędzi cop.filter(bi,bimg); //wykonujemy operację splotu biop = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); //definiujemy operację skalowania i interpolacji obrazu g2.drawimage(bimg,biop,x,y); //rysujemy skalowany obraz [74]

Efekty brzegowe EDGE_ZERO_FILL - krawędzie obrazu decelowego są wypełniane wartością 0. EDGE_NO_OP piksele obrazu źródłowego leżące na jego krawędzi są kopiowane w odpowiednie miejsca obrazu docelowego bez jakichkolwiek modyfikacji. [75]

Mapa kolorów (lookup table) [76] Poniższy przykład demonstruje zastosowanie mapy kolorów: byte reverse[] = new byte[256]; for (int j=0; j<200; j++){ } reverse[j]=(byte)(256-j); ByteLookupTable blut=new ByteLookupTable(0, reverse); LookupOp lop = new LookupOp(blut, null);

Modyfikacja jasności/kontrastu Poniższy przykład demonstruje zastosowanie operatora RescaleOp: RescaleOp rop = new RescaleOp(1.5f, 1.0f, null); rop.filter(bi,bimg); [77]