Elementi di
programmazione grafica
Contenuti
• Programmazione di semplici applicazioni
grafiche che
 Disegnano semplici forme geometriche
 Utilizzano colori
 Compongono forme semplici per formare figure
complesse
 Utilizzano “input dialogs” per ottenere input dall’utente
• Sviluppo di test per validare la correttezza
delle applicazioni
Frames
•
La classe JFrame
JFrame frame = new JFrame();
frame.setSize(300, 400);
frame.setTitle(“Un frame vuoto");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
•
import javax.swing.*;
Frames
File EmptyFrameViewer.java
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
17:
18:
import javax.swing.*;
class EmptyFrameViewer
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
final int FRAME_WIDTH = 300;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle(“Un frame vuoto");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Mini Test
1. Come disegnamo un frame quadrato con
titolo "Hello, World!"?
2. Come scriviamo un programma che lancia
due frames?
Risposte
1. Modifca EmptyFrameViewer come segue:
frame.setSize(300, 300);
frame.setTitle("Hello, World!");
2. Costruisci due oggetti JFrame definendone
la dimensione e poi invoca
setVisible(true) su ciascuno
Disegno di forme geometriche
• JComponent
 La classe che definisce contenitori generici, al
al cui interno includiamo forme geometriche
• Figure geometriche incluse in nuovi
JComponent
class ShapeComponent extends JComponent
{
. . .
}
• Un nuovo JComponent
Disegno di forme geometriche
• paintComponent
 il metodo invocato (automaticamente) tutte le volte
che il componente per il quale e` definito viene
ridisegnato
 è in questo metodo che si produce il disegno
class ShapeComponent extends JComponent
{
public void paintComponent(Graphics g)
{
// Converti in Graphics2D
Graphics2D g2 = (Graphics2D) g;
. . .
}
}
Disegno di forme geometriche
• Graphics classe che permette di
manipolare lo stato della componente grafica
(posizione/colore corrente)
• Graphics2D classe con metodi per la
creazione e il disegno di figure geometriche
• Usa un cast per ottenere un oggetto di tipo
Graphics2D dal parametro di tipo Graphics
Rectangle r = new Rectangle(5, 10, 20, 30);
g2.draw(rect);
• package java.awt
File ShapeComponent.java
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
import
import
import
import
import
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Rectangle;
javax.swing.JPanel;
javax.swing.JComponent;
/**
Un Component che disegna due rettangoli.
*/
class ShapeComponent extends JComponent
{
public void paintComponent(Graphics g)
{
// Ottieni un graphics2D
Graphics2D g2 = (Graphics2D) g;
Continua…
File ShapeComponent.java
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27: }
// Costruisci un rettangolo e disegna
Rectangle r = new Rectangle(5, 10, 20, 30);
g2.draw(r);
// Trasla il rettangolo (15 a dx, 25 in basso)
r.translate(15, 25);
// Disegna il rettangolo traslato
g2.draw(r);
}
Applicazioni
• ShapeViewer
 classe che lancia una finestra all’interno della quale
vengono raffigurate Ie componenti
 L’applicazione è costruita interamente all’interno del
metodo main della classe
 Disegna due rettangoli
Continued…
Applicazione ShapeViewer
Il metodo main
1. Costruisci il frame
2. Costruisci un oggetto della classe component
ShapeComponent component = new ShapeComponent();
3. Aggiunti il component al frame
frame.add(component);
La chiamata è leggermente più complicata per
versioni di Java precedenti alla 5:
frame.getContentPane().add(component);
4. Rendi visibile il frame
File ShapeViewer.java
01: import javax.swing.JFrame;
02:
03: class ShapeViewer
04: {
05:
public static void main(String[] args)
06:
{
07:
JFrame frame = new JFrame();
08:
09:
final int FRAME_WIDTH = 300;
10:
final int FRAME_HEIGHT = 400;11:
12:
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
13:
frame.setTitle(“Due rettangoli");
14:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
15:
Continua…
File ShapeViewer.java
16:
17:
18:
19:
20:
21: }
ShapeComponent component = new ShapeComponent();
frame.add(component);
frame.setVisible(true);
}
Mini Test
3. Che succede se sostituiamo la chiamata
g2.draw(box)con g.draw(box) ?
Risposta
3. Il compilatore segnala un errore
g : Graphics non ha un metodo draw
Applets
• Applets sono applicazioni eseguite
all’interno di un browser
• L’implementazione di un Applet utilizza il
pattern seguente:
public class MyApplet extends JApplet
{
public void paint(Graphics g)
{
// Ottieni un contesto grafico
Graphics2D g2 = (Graphics2D) g;
// Istruzioni per il disegno
. . .
}
}
Applets
•
La struttura è molto simile a quella di un
JComponent, con due differenze:
1. Estendiamo JApplet, invece di JComponent
2. IL codice del disegno è parte del metodo paint,
invece che del metodo paintComponent
•
Per eseguire un applet, dobbiamo creare un
file HTML ed inserire il codice che lancia
l’applet mediante la tag applet
Applets
• Un file HTML può avere diversi applets,
ciascuno dei quali introdotto da una
corrispondente tag (di tipo applet)
• Un applet può essere lanciato mediante
l’appletviewer, o all’interno di un browser
in cui Java sia stato abilitato.
appletviewer RectangleApplet.html
File ShapeApplet.java
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
import
import
import
import
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Rectangle;
javax.swing.JApplet;
/**
Un applet che disegna due rettangoli.
*/
public class ShapeApplet extends JApplet
{
public void paint(Graphics g)
{
// Ottieni un contesto grafico
Graphics2D g2 = (Graphics2D) g;
Continua…
File ShapeApplet.java
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27: }
// Costruisci un rettangolo e disegna
Rectangle r = new Rectangle(5, 10, 20, 30);
g2.draw(r);
// Trasla il rettangolo (15 a dx, 25 in basso)
r.translate(15, 25);
// Disegna il rettangolo traslato
g2.draw(r);
}
File ShapeAppletViewer.html
<html>
<head>
<title>Due rettangoli</title>
</head>
<body>
<p>Ecco qui il mio primo applet:</p>
<applet code="RectangleApplet.class" width="300" height="400">
</applet>
</body>
</html>
Applets
Forme Geometriche
• Rectangle, Ellipse2D.Double,
Line2D.Double fornite dal package java.awt
• Alcune di queste classi, e.g. Line2D.Double,
sono interne. Per il momento ignoriamo questo
aspetto, ma notiamo la dichiarazione import
import java.awt.geom.Ellipse2D; // no .Double
• Per disegnare una forma dobbiamo costruirla e
disegnarla
Ellipse2D.Double e = new Ellipse2D.Double(x, y, width, height);
g2.draw(e);
Una ellisse e la sua bounding box
Linee
• Due modi per disegnare una linea:
Line2D.Double segmento = new Line2D.Double(x1, y1, x2, y2);
oppure,
Point2D.Double from = new Point2D.Double(x1, y1);
Point2D.Double to = new Point2D.Double(x2, y2);
Line2D.Double segmento = new Line2D.Double(from, to);
Stringhe
g2.drawString("Message", 50, 100);
Domande
4. Quale è la sequenza di istruzioni per
disegnare un cerchio con centro (100, 100)
e raggio 25?
5. Quale è la sequenza di istruzioni per
disegnare la lettera "V" con due segmenti di
linea ?
6. Quale è la sequenza di istruzioni per
disegnare la stringa costituita dalla lettera
"V" ?
Risposte
4.
5.
6.
g2.draw(new Ellipse2D.Double(75, 75, 50, 50);
Line2D.Double segm1 = new Line2D.Double(0, 0, 10, 30);
g2.draw(segm1);
Line2D.Double segm2 = new Line2D.Double(10, 30, 20, 0);
g2.draw(segm2);
g2.drawString("V", 0, 30);
Colori
• Colori standard Color.BLUE, Color.RED, …
• Nuovi colori: formato rgb settando i valori delle
componenti red, green, blue tra 0.0F e 1.0F
Color magenta = new Color(1.0F,0.0F,1.0F), // F = float
• setColor setta il colore del Graphic Contexts
g2.setColor(magenta);
• Usa il colore con i metodi draw e fill
g2.fill(rectangle); // riempito con il colore corrente
Domanda
7.
Quale è la sequenza di istruzioni per
disegnare un quadrato giallo su uno
sfondo rosso?
Risposta
7.
Disegna un quadrato giallo all’interno di un
quadrato rosso:
g2.setColor(Color.RED);
g2.fill(new Rectangle(0, 0, 200, 200));
g2.setColor(Color.YELLOW);
g2.fill(new Rectangle(50, 50, 100, 100));
Forme complesse
• Best practice: costruisci un classe per
ciascuna forma
class Car
{
. . .
public void draw(Graphics2D g2)
{
// Istruzioni per il disegno
. . .
}
}
• Progetta la forma individuando le
componenti base
Due automobili
Progetto della Forma
Origine e punto di
riferimento della forma
File Car.java
01:
02:
03:
04:
05:
06:
07:
08:
import
import
import
import
import
java.awt.Graphics2D;
java.awt.Rectangle;
java.awt.geom.Ellipse2D;
java.awt.geom.Line2D;
java.awt.geom.Point2D;
/**
Una forma di auto posizionabile posizionabibile in un
un punto qualunque di una finestra.
09: */
10: public class Car
11: {
12:
/**
13:
Costruisce una auto a partire da una data origine
14:
@param x la coordinata x dell’origine
15:
@param y la coordinata y dell’origine
16:
*/
Continua…
File Car.java
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
public Car(int x, int y)
{
xLeft = x;
yTop = y;
}
/**
Disegna l’auto.
@param g2 il contesto grafico per il disegno
*/
public void draw(Graphics2D g2)
{
Rectangle scocca
= new Rectangle(xLeft, yTop + 10, 60, 10);
Ellipse2D.Double ruotaAnteriore
= new Ellipse2D.Double(xLeft + 10, yTop
+ 20, 10, 10);
Continua…
Ellipse2D.Double ruotaPosteriore
File Car.java
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
= new Ellipse2D.Double(xLeft + 40, yTop
+ 20, 10, 10);
// estremo inferiore del parabrezza
Point2D.Double p1
= new Point2D.Double(xLeft + 10,
// estremo anteriore del tetto
Point2D.Double p2
= new Point2D.Double(xLeft + 20,
// estremo posteriore del tetto
Point2D.Double p3
= new Point2D.Double(xLeft + 40,
// estremo inferiore del lunotto
Point2D.Double p4
= new Point2D.Double(xLeft + 50,
Line2D.Double frontWindshield
= new Line2D.Double(p1, p2);
yTop + 10);
yTop);
yTop);
yTop + 10);
Continued…
File Car.java
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68: }
Line2D.Double roofTop
= new Line2D.Double(p2, p3);
Line2D.Double rearWindshield
= new Line2D.Double(p3, p4);
g2.draw(scocca);
g2.draw(ruotaAnteriore);
g2.draw(ruotaPosteriore);
g2.draw(parabrezza);
g2.draw(tetto);
g2.draw(lunotto);
}
public static int WIDTH = 60;
public static int HEIGHT = 30;
private int xLeft;
private int yTop;
Costruiamo l’applicazione
JComponent contenente il disegno
• Ricordiamo: istruzioni per il disegno nel
metodo paintComponent
• Posizione in basso a dx:
int x = getWidth() – Car.WIDTH;
int y = getHeight()– Car.HEIGHT;
Car bottomCar = new Car(x, y);
• getWidth e getHeight chiamati sull’oggetto
che esegue paintComponent
• Se cambia la dimensione della finestra
paintComponent viene invocato e la posizione
dell’auto ricalcolata
Continua…
File CarComponent.java
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
/**
This component draws two car shapes.
*/
class CarComponent extends JComponent
{
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Car topCar = new Car(0, 0);
Continua…
File CarComponent.java
16:
17:
18:
19:
20:
21:
22:
23:
24: }
int x = getWidth() - Car.WIDTH;
int y = getHeight() - Car.HEIGHT;
Car bottoCar = new Car(x, y);
topCar.draw(g2);
bottomCar.draw(g2);
}
• Il metodo draw della classe Car invoca i
metodi del contesto grafico g2 per comporre
il disegno
L’applicazione CarViewer.java
01: import javax.swing.JFrame;
02:
03: public class CarViewer
04: {
05:
public static void main(String[] args)
06:
{
07:
JFrame frame = new JFrame();
08:
09:
final int FRAME_WIDTH = 300;
10:
final int FRAME_HEIGHT = 400;
11:
12:
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
13:
frame.setTitle("Two cars");
14:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Continua…
File CarViewer.java
15:
16:
17:
18:
19:
20:
21: }
CarComponent component = new CarComponent();
frame.add(component);
frame.setVisible(true);
}
Domanda
8.
Quale classe dobbiamo modificare per
ottenere un disegno in cui le auto sono
disposte una vicino all’altra?
Risposta
8.
CarComponent
Altre forme grafiche
Rectangle fasciaVerde = new
Rectangle fasciaRossa = new
Line2D.Double topLine
= new Line2D.Double(130,
Line2D.Double bottomLine
= new Line2D.Double(130,
Rectangle(100, 100, 30, 60);
Rectangle(160, 100, 30, 60);
100, 160, 100);
160, 160, 160);
Lettura da un dialog box
• In una una applicazione grafica può
possiamo interagire con l’utente chiedendo
input mediante un JOptionPane
• Il metodo showInputDialog attiva una
finestra che dà un prompt e attende input
• Il metodo showInputDialog restituisce la
stringa fornita dall’utente
String input = JOptionPane.showInputDialog("Enter x");
double x = Double.parseDouble(input);
Continua…
Un dialog box
ColorViewer
• Una applicazione che permette all’utente di
comporre un colore decidendo i parametri
del formato rgb
• I valori vengono richiesti in seguenza
mediante dialog boxes
• Al termine l’applicazione attiva una finestra
con un quadrado del colore composto
dall’utente
File ColorViewer.java
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
17:
18:
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
class ColorViewer
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
final int FRAME_WIDTH = 300;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String input;
Continua…
File ColorViewer.java
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38: }
// Chiedi all’utente I valori di red, green, blue
input = JOptionPane.showInputDialog("red:");
double red = Double.parseDouble(input);
input = JOptionPane.showInputDialog("green:");
double green = Double.parseDouble(input);
input = JOptionPane.showInputDialog("blue:");
double blue = Double.parseDouble(input);
Color coloreScelto = new Color(
(float) red, (float) green, (float) blue);
DemoColorComponent component
= new DemoColorComponent(fillColor);
frame.add(component);
frame.setVisible(true);
}
File DemoColorComponent.java
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
import
import
import
import
import
java.awt.Color;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.Rectangle;
javax.swing.JComponent;
/**
Una componente che include un quadrato colorato
*/
class DemoColorComponent extends JComponent
{
private Color fillColor; // colore di riempimento
/**
Costruisce la componente
@param c il colore di riempimento del quadrato
*/
public DemoColorComponent(Color c)
Continua…
File DemoColorComponent.java
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
{
fillColor = c;
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
// Seleziona il colore del contesto grafico
g2.setColor(fillColor);
// Costruisci e colora un quadrato al centro
// della finestra
Continua…
File DemoColorComponent.java
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
43: }
final int LATO = 100;
Rectangle quadrato = new Rectangle(
(getWidth() - LATO) / 2,
(getHeight() - LATO) / 2,
LATO,
LATO);
g2.fill(quadrato);
}
Output
Domande
9.
Sarebbe possibile chiedere i tre valori per
r,g, e b in un unico dialog box?
10. Perché l’applicazione invoca
showInputDialog dal metodo main main
della classe ColorViewer e non dal
metodo paintComponent della classe
ColorComponent?
Risposte
9.
Certo, ma in quel caso è necessario
estrarre poi le singole componenti … un
utile esercizio di semplice programmazione
su stringhe
10. Perchè in quel caso i dialog box
verrebbero rilanciati tutte le volte che la
finestra viene mossa / resized /
deiconificata /…
Scarica

ch05graphics