Progetto di applicazioni grafiche Disegno di forme complesse • Prassi : un classe per ciascuna forma class Car { . . . public void draw(Graphics2D g) { // Istruzioni per il disegno . . . } } • Progetta la forma individuando le componenti base Esempio: 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 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 parabrezza = new Line2D.Double(p1, p2); yTop + 10); yTop); yTop); yTop + 10); Continua… File Car.java 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: } Line2D.Double tetto = new Line2D.Double(p2, p3); Line2D.Double lunotto = 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 bottomCar = 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 possiamo dare input mediante un JOptionPane • Il metodo showInputDialog attiva una finestra che dà un prompt e attende input 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 quadrato 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); ColorComponent component = new ColorComponent(coloreScelto); frame.add(component); frame.setVisible(true); } File ColorComponent.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 ColorComponent extends JComponent { private Color fillColor; // colore di riempimento /** Costruisce la componente @param c il colore di riempimento del quadrato */ public ColorComponent(Color c) Continua… File ColorComponent.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 ColorComponent.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 su stringhe 10. Perchè in quel caso i dialog box verrebbero rilanciati tutte le volte che la finestra viene mossa / resized / deiconificata /…