Table of Contents

Program w języku Java

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.

Tworzymy aplet

Projekt

Wybierz File → New → Java Project. Wprowadź ShapesApplet jako nazwę projektu.

Utworzony zostanie pusty projekt.

Klasa ShapesApplet

Wybierz File → New → Java Class

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.

Dodajemy do apletu rysowanie wektorów

Dodajemy klasę Shape

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){}
 
}

Dodajemy klasę Line

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);
	}
 
}

Dodajemy klasę Circle i Rectangle

Pierwsza refaktoryzacja

Nie podoba nam się występujące w trzech miejscach g.setColor( c ). Bardziej podobałoby się g.setColor(color).

Zmieniamy nazwę odziedziczonego atrybutu

Dodajemy ShapeFactory

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:

Piszemy 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;
	}

Modyfikujemy kod apletu

	static final int SIZE = 100;
	Shape[]table = new Shape[SIZE];
	public ShapesApplet(){
		for(int i=0;i<SIZE;i++){
			table[i]=ShapeFactory.get().createRandomShape();
		}
	}
	public void paint(Graphics g){
		for(Shape s:table){
			s.draw(g);
		}
	}
Uruchamiamy

Dodajemy kolory

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…

Refaktoryzacja: dodawanie parametru do istniejącej funkcji

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

Zmieniamy kod funkcji

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.

Dodajemy losową generację kolorów

	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…

Dystrybucja apletu

Tworzymy archiwum jar

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.

Dodajemy stronę HTML

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. 8-o Niestety - nie udaje się uruchomić apletu? Nie pozwalają na to domyślne ustawienia przeglądarki.

Podpisujemy aplet

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

Otwieramy lokalny plik w przeglądarce

Jeśli udało się wykonać poprzedni krok - możemy załadować plik do przeglądarki z lokalnego systemu plików. Możemy go także umieścić na serwerze HTTP (jesli mamy do niego dostęp).