Celem zajęć będzie rozwinięcie prostego apletu - czyli programu osadzonego na stronie HTML…
Program będzie bardzo podobny do poprzedniego napisanego w języku C++, również pojawi się w nim hierarchia Shape oraz ShapeFactory.
Wybierz File → New → Java Project. Wprowadź ShapesApplet
jako nazwę projektu.
Utworzony zostanie pusty projekt.
Wybierz File → New → Java Class
ShapesApplet
pl.edu.agh.kis.snwo
Wprowadź metodę paint()
i nie zapomnij o extends Applet
. Metoda paint()
zostanie wywołana za każdym razem, kiedy trzeba będzie przerysować okno apletu.
public class ShapesApplet extends Applet{ /** * */ public void paint(Graphics g){ g.drawLine(10, 10, 100, 100); g.drawLine(10, 100, 100, 10); } }
Wybierz Run i jako konfigurację wskaż Run as applet. Uruchomione zostanie narzędzie appletviewer, a w nim narysowane dwie skrzyżowane linie.
Aby wyświetlić aplet w oknie przeglądarki, jego kod musi być osadzony na stronie HTML. Przykładowa strona wygląda następująco:
<html> <head> <title>Shapes Applet</title> </head> <body> <applet code="pl.edu.agh.kis.snwo.ShapesApplet.class" width="1200" height="700" /> </body> </html>
Po przesłaniu plików na serwer…
…i wybraniu odpowiedniego adresu w oknie przeglądarki aplet uruchomi się.
Proszę zwrócić uwagę na rozmieszczenie plików. Każdy człon nazwy pakietu odpowiada katalogowi.
Wybierz File → New → Java Class i jako nazwę klasy wprowadź Shape
.
Klasa powinna trafić do pakietu pl.edu.agh.kis.snwo
package pl.edu.agh.kis.snwo; import java.awt.Color; import java.awt.Graphics; public class Shape { Color c=Color.black; void draw(Graphics g){} }
Wybierz File → New → Java Class i jako nazwę klasy wprowadź Line
. Wprowadź w polu superclass (klasa bazowa) Shape
.
Wprowadź kod:
package pl.edu.agh.kis.snwo; import java.awt.Graphics; public class Line extends Shape { int x1; int y1; int x2; int y2; void draw(Graphics g){ g.setColor(c); g.drawLine(x1, y1, x2, y2); } }
draw
wywołując g.drawOval()
oraz g.drawRect()
. Proszę przeczytać ich opisy, aby poprawnie je wywołać.
Nie podoba nam się występujące w trzech miejscach g.setColor( c )
. Bardziej podobałoby się g.setColor(color)
.
Zmieniamy nazwę odziedziczonego atrybutu
Shape.java
.c
i wybieramy Refactor→Rename…. color
Odtworzymy projekt klasy zaimplementowanej w języku C++
public class ShapeFactory { private ShapeFactory(){} private static ShapeFactory _theFactory = new ShapeFactory(); static ShapeFactory get(){return _theFactory;} Shape createLine(int x1,int y1,int x2,int y2){ Line s= new Line(); s.x1=x1; s.x2=x2; s.y1=y1; s.y2=y2; return s; } Shape createCircle(int x,int y,int r){ //... } Shape createRectangle(int x1,int y1,int x2,int y2){ //... } }
Jak poprzednio:
get()
pozwala zrealizować do niej dostępShapeFactory.get().createRandomShape()
W metodzie createRandomShape()
była wołana funkcja rand()
. Napiszemy ją, aby nie przerabiać kodu
Random generator = new Random(System.currentTimeMillis()); private int rand(){ return generator.nextInt(1234567); } Shape createRandomShape(){ int choice = rand()%3; switch(choice){ case 0: return createLine(rand()%300,rand()%300,rand()%800,rand()%900); case 1: return createCircle(rand()%900,rand()%900,rand()%300); case 2: return createRectangle(rand()%300,rand()%300,rand()%800,rand()%900); } return null; }
Shape
o rozmiarze SIZE
static final int SIZE = 100; Shape[]table = new Shape[SIZE];
public ShapesApplet(){ for(int i=0;i<SIZE;i++){ table[i]=ShapeFactory.get().createRandomShape(); } }
paint()
. Mam nadzieję, że rozpoznajecie Państwo konstrukcję foreach.public void paint(Graphics g){ for(Shape s:table){ s.draw(g); } }
Oczywiście, mogliśmy od razu wprowadzić docelowy kod, ale celem jest zapoznanie się z możliwościami refaktoryzacji. Więc kolory dodajemy później…
Poza losową generacją rozmiarów wektorów, chcemy, aby miały one losowo wybrane kolory. Funkcje createLine()
, createRectangle()
i createCircle()
raczej nie powinny losować kolorów. Przekażemy je do nich jako parametr ustawiany w createRandomShape
createLine()
w kodzie ShapeFactory
. Color color
createRandomShape()
Color color
pojawił się na początku.Tak, jak poniżej – musimy coś z parametrem kolor zrobić.
Shape createLine(Color color,int x1,int y1,int x2, int y2){ Line s= new Line(); s.color=color; s.x1=x1; s.x2=x2; s.y1=y1; s.y2=y2; return s; }
Wprowadzamy s.color=color;
dla Rectangle
i Circle
.
Shape createRandomShape(){ Color color = new Color(rand()%256,rand()%256,rand()%256); int choice = rand()%3; switch(choice){ case 0: return createLine(color,rand()%300,rand()%300,rand()%800, rand()%900); case 1: return createCircle(color,rand()%900,rand()%900, rand()%300); case 2: return createRectangle(color,rand()%300,rand()%300,rand()%800, rand()%900); } return null; }
i po uruchomieniu otrzymujemy…
Programy napisane w Javie z reguły są dystrybuowane w postaci archiwów jar. Nazwa jest luźno związana ze słoikiem Raczej jest to skrót od Java ARchive. W gruncie rzeczy jest to zwykły zip, w którym umieszczany jest skompilowany kod klas oraz (opcjonalnie) dodatkowe pliki zawierające klucze użyte do podpisu i sumy kontrolne plików class.
build
. Wybierz File→New→Folder
W odróżnieniu od poprzedniego przykładu pojawił się atrybut archive=“ShapesApplet.jar”
<html> <head> <title>Shapes Applet</title> </head> <body> <applet code="pl.edu.agh.kis.snwo.ShapesApplet.class" archive="ShapesApplet.jar" width="1200" height="700" /> </body> </html>
Następnie otwieramy ją w przeglądarce. Niestety - nie udaje się uruchomić apletu? Nie pozwalają na to domyślne ustawienia przeglądarki.
Zazwyczaj przeglądarka pozwala na uruchomienie podpisanego apletu, nawet przy użyciu testowego certyfikatu. Ten docelowy powinna wygenerować zaufana instytucja (i pobrać za to opłatę).
Podpisywanie pliku jar jest procesem dwuetapowym:
"c:/Program Files/Java/jdk1.6.0_31/bin/keytool.exe" -genkey -alias mojeid "c:/Program Files/Java/jdk1.6.0_31/bin/jarsigner.exe" ShapesApplet.jar mojeid