Enrera
Mòdul 6
Iniciació a la programació en Java
  Pràctica
1
2
3
4
   
Exercicis
Exercicis
 
 
  Pintar...
   
  Sovint convé presentar a l'usuari alguna mena de diagrama, de dibuix, de representació. Això implica la necessitat de disposar d'algun conjunt de classes i mètodes que ens permetin elaborar aquests diagrames, dibuixos i representacions. La classe java.awt.Canvas i les seves classes associades (java.awt.Graphics) ens donen les eines per respondre a això.
   
  L'objectiu d'aquesta pràctica és, per tant, començar a exercitar-se amb la classe java.awt.Canvas. De passada ampliarem una mica el coneixement sobre la classe java.awt.Font, el qual havíem iniciat a la pràctica 4 del mòdul 5. I encara més: farem servir algun dels mètodes i classes del paquet (package) java.awt.io, destinats a gestionar l'entrada i sortida de dades a fitxers.
   
Pintant sobre un Canvas
   
Atenció !
La classe bàsica és java.awt.Canvas, la qual representa una àrea de la pantalla, rectangular i en blanc, en la qual l'aplicació pot dibuixar-hi o bé capturar esdeveniments generats per l'usuari i localitzats en punts concrets, sovint accions del ratolí.
  • La classe java.awt.Canvas és un component però no és un contenidor (container). Això implica que podem posar un canvas a qualsevol container, però que no podem posar components en un canvas: un canvas no té cap layout manager per organitzar-ne els components!

  • Allò que veiem, doncs, en un canvas, no són pas objectes sinó que tot hi és pintat. Per tant, ara sí que són importants alguna mena de coordenades que ens descriguin posicions: en un canvas, les coordenades són nombres enters (int) que compten píxels. El punt o píxel (0,0) és a dalt a l'esquerra, la primera coordenada (x, width o similar) creix d'esquerra a dreta i la segona (y, height, etc.) de dalt a baix


  • Com qualsevol component, un canvas té un color de fons (background) i un color de traçat (foreground) heretats del contenidor en el qual resideix, que es es poden canviar mitjançant els mètodes public void setBackground(Color color) i public void setForeground(Color color).

  • La gestió del pintat efectiu es confia a la classe java.awt.Graphics. Els seus mètodes, entre els quals

    • public void draw3DRect(int x, int y, int width, int height, boolean raised),

    • public abstract void drawLine(int x1, int y1, int x2, int y2),

    • public abstract void drawOval(int x, int y, int width, int height),

    • public abstract void drawPolygon(int[] xPoints, int[] yPoints, int nPoints),

    • public abstract void drawPolyline(int[] xPoints, int[] yPoints, int nPoints),

    • public void drawRect(int x, int y, int width, int height),

    • public abstract void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight),

    • public abstract void drawString(String str, int x, int y),

    • public void fill3DRect(int x, int y, int width, int height, boolean raised),

    • public abstract void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle),

    • public abstract void fillOval(int x, int y, int width, int height),

    • public abstract void fillPolygon(int[] xPoints, int[] yPoints, int nPoints),

    • public abstract void fillRect(int x, int y, int width, int height),

    • public abstract void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight),

    • public abstract void setColor(Color c),

    • public abstract void setFont(Font font),

    (vegeu la documentació de la classe java.awt.Graphics)

  • En una primera aproximació, podem considerar que un canvas té associat un objecte graphics que és qui el pinta. Hom en diu el context gràfic del canvas. Per pintar necessitem fer una crida a aquest objecte graphics mitjançant el mètode public Graphics getGraphics() de la classe java.awt.Component, mare de la classe java.awt.Canvas.

  • La classe java.awt.Canvas té el mètode public void paint(Graphics g), que gairebé sempre cal sobreescriure (override). Aquest mètode contindrà les instruccions necessàries per tal que es pinti allò que desitgem.

  • L'altre mètode essencial de la classe java.awt.Canvas és public void update(Graphics g), el qual convé no sobreescriure. Per defecte, l'execució d'aquest métode consisteix en:

    1. omplir el canvas amb el color de fons i, per tant, fer desaparèixer tot allò que hi havia pintat,

    2. executar el mètode paint.

    Hom pot cridar aquest mètode directament des d'altres objectes mitjançant el mètode de la classe java.awt.Component (mare de java.awt.Canvas) public void repaint(). L'execució es fa llavors sobre el context gràfic del canvas.
   
Posem tot això en funcionament:
   
Pràctica Creem el projecte Pintura com a "Basic Java Application" amb el codi següent:
   
  /*
* @(#)Pintura.java 1.0 02/10/21
*
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_1\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/
  //package myprojects.pintura;
  import java.awt.*;
import java.awt.event.*;

class Pintura extends Frame {

    public Pintura() { //constructor

          ElMeuCanvas canvas=new ElMeuCanvas();
        setBackground(Color.BLACK);
        setForeground(Color.YELLOW);
        add(canvas,BorderLayout.CENTER);
          addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                dispose();
                System.exit(0);
            }
        });
    }

    public static void main(String args[]) {
        System.out.println("Starting Pintura...");
        Pintura mainFrame = new Pintura();
        mainFrame.setSize(400, 400);

          mainFrame.setTitle("Canvas");
          mainFrame.setVisible(true);
    }
}
 

class ElMeuCanvas extends Canvas {

    public ElMeuCanvas () { //constructor
        super();
    }

    public void paint (Graphics g) {
        g.drawLine(5,15,150,65);
    }

}

   
  A l'executar-lo el resultat és aquest:
   
 
   
   
Quin és el quid de la qüestió?
   
Atenció !

Hem hagut de fer la subclasse ElMeuCanvas per tal de sobreescriure-li el mètode public void paint(Graphics g) i posar-li què calia pintar. El color de fons (background), negre, és el del frame al qual pertany i la línia s'ha dibuixat groga, que és el color de traç (foreground) també del frame. Aquests colors s'han fixat al constructor del frame, a les línies de codi

        setBackground(Color.BLACK);
        setForeground(Color.YELLOW);

Ara cal jugar amb això:

   
Pràctica
  • Comencem per intercalar una nova línia al mètode paint, just abans de l'instrucció que fa pintar la línia:

        public void paint (Graphics g) {
            g.setColor(Color.RED);
            g.drawLine(5,15,150,65);
        }

    i la línia es dibuixa ara de color vermell...

  • Podem, també, combinar colors i dibuixos:

        public void paint (Graphics g) {
            g.setColor(Color.RED);
            g.fillOval(25,15,150,75);
            g.setColor(Color.BLUE);
            g.fillRect(80,60,140,90);
            g.setColor(Color.CYAN);
            g.fillRoundRect(180,90,140,90,40,20);
        }

  • Si volem canviar el color del fons sense tocar el color de fons (background) del contenidor ni el color del fons (background) del canvas cal, primer de tot, conèixer quines són les dimensions del canvas (variables segons el layout manager!). Per fer-ho acudim al mètode public Dimension getSize() de la classe java.awt.Component (classe mare de java.awt.Canvas). Aquest mètode ens retorna les mides del canvas en forma d'un objecte java.awt.Dimension. La variable public int width n'és l'amplada i public int height n'ès l'alçada, ambdues en pixels. Llavors, només cal dibuixar un rectangle d'aquestes dimensions amb el color adequat. El següent mètode posa el fons groc clar:

        public void paint (Graphics g) {
            Dimension dimension=getSize();
            g.setColor(new Color(255,255,200));
            g.fillRect(0,0,dimension.width,dimension.height);
            g.setColor(Color.RED);
            g.fillOval(25,15,150,75);
            g.setColor(Color.BLUE);
            g.fillRect(80,60,140,90);
            g.setColor(Color.CYAN);
            g.fillRoundRect(180,90,140,90,40,20);
        }

  • Per dibuixar textos podem fer:

        public void paint (Graphics g) {
            Dimension dimension=getSize();
            g.setColor(new Color(255,255,200));
            g.fillRect(0,0,dimension.width,dimension.height);
            g.setColor(Color.RED);
            g.fillOval(25,15,150,75);
            g.setColor(Color.BLUE);
            g.fillRect(80,60,140,90);
            g.setColor(Color.CYAN);
            g.fillRoundRect(180,90,140,90,40,20);
            g.setColor(Color.WHITE);
            g.drawString("Això és un text",100,120);
        }

  • I, per canviar el font,

        public void paint (Graphics g) {
            Dimension dimension=getSize();
            g.setColor(new Color(255,255,200));
            g.fillRect(0,0,dimension.width,dimension.height);
            g.setColor(Color.RED);
            g.fillOval(25,15,150,75);
            g.setColor(Color.BLUE);
            g.fillRect(80,60,140,90);
            g.setColor(Color.CYAN);
            g.fillRoundRect(180,90,140,90,40,20);
            Font f=new Font("SansSerif",Font.PLAIN,30);
            g.setColor(Color.WHITE);
            g.drawString("Això és un text",100,120);
        }

   
La classe java.awt.Font (II):
   
Atenció ! Ara és el moment d'ampliar una mica el coneixement de la classe java.awt.Font i estudiar com podem fer servir els fonts físics, a més dels fonts lògics, que ja sabíem manipular (vegeu la pràctica 4 del mòdul 5)
   
 
  • Recordem que els fonts físics són els fonts que resideixen en el sistema en el qual s'executa l'aplicació Java, que a WindowsXX són els fonts que resideixen a la carpeta C:\WINDOWS\FONTS o similar: ARIAL.TTF, COURIER NEW NORMAL.TTF, TIMES.TTF, etc. i que la Màquina Virtual de Java és capaç, com a mínim, de tractar amb fonts de tecnologia TrueType.

  • Ja es veu que si la nostra aplicació,ha de fer servir fonts físics,per començar ha de ser capaç de llegir els fitxers *.TTF del disc. D'entrada això implica l'ús d'algunes classes del package java.io que estan pensades justament per a que Java tracti amb fitxers. Per tant, la primera cosa a fer és importar el package java.io:

    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;

  • A continuació, cal crear una instància de la classe java.io.File que representi el fitxer *.TTF que conté el font:

    File file=new File("C:/WINDOWS/FONTS/TIMES.TTF");

  • Ara cal construir una instància de la classe java.io.FileInputStream (filla de la classe més general java.io.InputStream) que representa la lectura del fitxer:

    FileInputStream fontStream=new FileInputStream(file);

  • Amb les dades del fitxer *.TTF ja llegides, ja podem construir el font. El mètode a fer servir és public static Font createFont(int fontFormat,InputStream fontStream) de la classe java.awt.Font. La variable int fontFormat és Font.TRUETYPE_FONT (vegeu la documentació de la classe java.awt.Font) i les dades són a fontStream:

    Font f=Font.createFont(Font.TRUETYPE_FONT,fontStream);

  • Ja només falta donar-li les mides desitjades. Fem servir el mètode public Font deriveFont(float size) i li donem la mida 28 (atenció! els valors float s'indiquen amb una "f"). Després establim aquest font pel context gràfic del canvas:

    f=f.deriveFont(28f);
    g.setFont(f);

  • Com que el mètode createFont llença les excepcions java.awt.FontFormatException i java.io.IOException, cal tancar-lo, junt amb les seves conseqüències, en una estructura try - catch. El codi resultant pel mètode paint és aquest:

        public void paint (Graphics g) {
            Dimension dimension=getSize();
            g.setColor(new Color(255,255,200));
            g.fillRect(0,0,dimension.width,dimension.height);
            g.setColor(Color.RED);
            g.fillOval(25,15,150,75);
            g.setColor(Color.BLUE);
            g.fillRect(80,60,140,90);
            g.setColor(Color.CYAN);
            g.fillRoundRect(180,90,140,90,40,20);
            File file=new File("C:/WINDOWS/FONTS/TIMES.TTF");
                try {
                    FileInputStream fontStream=
                                    new FileInputStream(file);
                    Font f=Font.createFont(Font.TRUETYPE_FONT,
                                           fontStream);
                    f=f.deriveFont(28f);
                    g.setFont(f);
                } catch (FontFormatException e) {
                    System.out.println(e.getMessage());
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            g.setColor(Color.WHITE);
            g.drawString("Això és un text",100,120);
        }

  • I el resultat és aquest:

   
Pràctica
Ara podeu experimentar amb fonts i mides diversos a partir dels fitxers *.TTF que hi hagi al vostre disc dur...
   
   
 
Amunt