venerdì 21 maggio 2010

Java: programmazione grafica (2)

La libreria grafica Graphics2D estende la vecchia versione (limitata nelle funzioni di disegno) implementando infiniti metodi per disegnare punti, linee e forme geometriche. A tale proposito, quando si descrive un pannello contenente forme grafiche e si riscrive il metodo paintComponent(), una delle prime operazioni da fare è quella di casting: Graphics2D g2=(Graphics2D)g. La variabile g2 verrà quindi usata per disegnare, spostare e riempire forme.
Alcune forme geometriche ci vengono date dalle classi Line2D, Rectangle2D ed Ellipse2D. Ogni classe che descrive una forma geometrica implementa l'interfaccia Shape.
Il disegno di forme geometriche è estremamente semplice, si istanzia una variabile di una qualunque forma geometrica (a breve vedremo i costruttori delle classi) indicando al costruttore le proprietà che essa deve rispettare (coordinate, larghezza e altezza, generalmente). Quindi attraverso la variabile oggetto g2 si disegna la forma nel pannello invocando il metodo draw().
Con l'oggetto g2 possiamo anche impostare il colore da usare per il tratto del disegno (metodo setPaint()) ed eventualmente riempire la forma (con il metodo fill()).
Ognuna delle classi citate sopra ha due implementazioni (interne), una per le coordinate di tipo float (Float) e una per le coordinate di tipo double (Double). Pertanto, va fatta molta attenzione, soprattutto quando con i metodi getWidth() e getHeight() si tenta di leggere le dimensioni della forma. I valori ritornati sono sempre double, va quindi applicato un casting se la variabile che raccoglie il valore è di tipo float!
Per disegnare un rettangolo occorrono le coordinate (i primi due parametri del costruttore) dell'angolo superiore sinistro. Vanno poi specificate la larghezza e l'altezza (i restanti due parametri del costruttore) della forma:

Rectangle2D rectangle=new Rectangle2D.Float(10,10,200,100);

Per disegnare un ellisse bisogna fare riferimento al rettangolo che racchiude la forma e specificare, anche in questo caso, i parametri visti prima (coordinate, larghezza e altezza).

Ellipse2D ellipse=new Ellipse2D.Float(10,10,200,100);

Per il disegno di linee si devono specificare al costruttore le coordinate dei punti iniziale e finale della linea:

Line2D line=new Line2D.Float(10,10,210,110);

Il pannello che disegna le forme potrebbe essere ad esempio descritto in questo modo:


class MyPanel extends JPanel {
   public void paintComponent(Graphics g) {
      Graphics2D g2=(Graphics2D)g;
      Rectangle2D rectangle=new Rectangle2D.Float(10,10,200,100);
      Line2D line=new Line2D.Float(margin,margin,(10,10,210,110);
      Ellipse2D ellipse=new Ellipse2D.Float(10,10,200,100);
      g2.draw(line);
      g2.draw(rectangle);
      g2.setPaint(Color.BLUE);
      g2.fill(ellipse);
      g2.draw(ellipse);
   }
   static final long serialVersionUID=-1L;
   static final float margin=10;
}

Un tipico problema: voglio disegnare delle forme proporzionandole alla dimensione della finestra. Come accedo alle dimensioni della finsetra?
Occorre, allora, realizzare la classe MyPanel (che estende JPanel) come classe interna alla classe MyFrame (che estende JFrame). Perché? Una classe interna può accedere ai campi dell'istanza della classe che la contiene! Nel nostro alle varibili width ed height.



class MyFrame extends JFrame {
   public MyFrame(String title, int width, int height, boolean isResizable) {
      this.title=title;
      this.width=width;
      this.height=height;
      setSize(width,height);
      setTitle(title);
      if (isResizable) setResizable(true);
      MyPanel graphicPanel=new MyPanel();
      Container contentPane=this.getContentPane();
      contentPane.add(graphicPanel);
   }
   public void centered() {
      Toolkit system=Toolkit.getDefaultToolkit();
      Dimension screenSize=system.getScreenSize();
      int screenWidth=screenSize.width;
      int screenHeight=screenSize.height;
      this.setLocation((screenWidth/2)-(width/2),(screenHeight/2)-(height/2));
   }
   private String title;
   private int width;
   private int height;
   static final long serialVersionUID=-1L;
   class MyPanel extends JPanel {
      public void paintComponent(Graphics g) {
         Graphics2D g2=(Graphics2D)g;
         Rectangle2D rectangle=new Rectangle2D.Float(margin,margin,width/2,height/2);
         line=new Line2D.Float(margin,margin,(width/2)+margin,(height/2)+margin);
         Ellipse2D ellipse=new Ellipse2D.Float(margin,margin,width/2,height/2);
         g2.draw(line);
         g2.draw(rectangle);
         g2.setPaint(Color.BLUE);
         g2.fill(ellipse);
         g2.draw(ellipse);
      }
      static final long serialVersionUID=-1L;
      static final float margin=10;
   }
}

Nessun commento:

Posta un commento