javabog.dk  |  << forrige  |  indhold  |  næste >>  |  programeksempler  |  om bogen

5 Grafiktegning (Java2D)


5.1 Java2D kort fortalt 94

5.1.1 Geometriske figurer 94

5.1.2 Geometriske operationer 95

5.1.3 Transformationer 96

5.1.4 Linjetyper 96

5.1.5 Tegnekvalitet 96

5.1.6 Videre læsning 96

5.2 Eksempel 96

5.3 Eksempel fra JDK'et 98

Java2D giver mulighed for mere avanceret grafikmanipulering. Blandt faciliteterne er:

5.1 Java2D kort fortalt

Java2D virker ved, at paint()-metoden får overført et Graphics-objekt, som i virkeligheden er et Graphics2D-objekt (Graphics2D arver fra Graphics).

Det typekonverterer man til Graphics2D og har så adgang til de ekstra funktioner i Java2D:

  public void paint(Graphics g)
  {
    Graphics2D g2 = (Graphics2D) g;
    ...
  }

Man kan derefter tegne med de normale funktioner fra Graphics-klassen, men også med nogle af de mange nye metoder i Graphics2D-klassen.

De gamle tegnemetoder (som drawLine(), drawRect(), ...) er erstattet med en enkelt, draw(), der kan tegne alle mulige geometriske figurer repræsenteret af Shape-objekter:

  Shape s = new Line2D.Float(0, 0, 100, 100);
  g2.draw(s);

5.1.1 Geometriske figurer

Shape-objekter (der findes i pakken java.awt.geom) repræsenterer en eller anden geometrisk figur på skærmen. Der findes disse grundlæggende Shape-objekter:

Klassen GeneralPath repræsenterer en vilkårlig figur, der er en kombination af ovenstående figurer (Shape-objekter):

  GeneralPath figur = new GeneralPath();
  figur.append( new Line2D.Float(0, 0, 100, 100), false );
  figur.append( new CubicCurve2D.Float(0, 0, 80, 15, 10, 90, 100, 100), false );
  figur.append( new Arc2D.Float(-30, 0, 100, 100, 60, -120, Arc2D.PIE), false );

Metoden append() tager et Shape-objekt og en boolean, der afgør om det nye Shape-objekt skal forbindes med den eksisterende figur eller ej.

GeneralPath har også metoderne moveTo(x, y), lineTo(x, y), quadTo(x,y,x2,y2) og curveTo(x, y, x1, y1, x2, y2) til at bygge en figur op med.

Man kan derefter tegne den resulterende figur med én kommando:

  g2.draw( figur );

Det samme GeneralPath-objekt kan med fordel bruges igen i hver gentegning for hurtigere kørselstid (hvis det oprettes et andet sted end i paint()-metoden).

5.1.2 Geometriske operationer

Med klassen Area kan man hurtigt udføre en række handlinger med shapeobjekter uden at beskrive hvert linjesegment eller kurve, som f.eks.:

add intersect

subtract exclusiveOr

Nedenfor er vist et lille eksempel på brugen af klassen Area.

import java.awt.*;
import java.awt.geom.*;  // indeholder klasser der er specielle for Java2D

public class FigurLeg extends Frame
{
  public void paint(Graphics g)
  {
    Graphics2D g2 = (Graphics2D)g;
    Area a = new Area(new Rectangle2D.Double(10,30,60,60));
    g2.draw(a);          

    Area b = new Area(new Ellipse2D.Double(10,10,90,50));
    g2.translate(100,0); // tegn i midten
    g2.draw(b);

    a.intersect(b);      // find fællesmængde af a og b og tegn yderst til højre
    g2.translate(100,0);
    g2.draw(a);
  }

  public static void main(String[] args) {
    FigurLeg fl = new FigurLeg();
    fl.setSize(300,100);
    fl.setVisible(true);
  }
}

Yderst til højre ses fællesmængden af firkanten og cirklen.

5.1.3 Transformationer

Klassen AffineTransform repræsenterer en lineær (affin) transformation af koordinatsystemet. Med den kan man lave skaleringer (større/mindre), drejninger (med/mod uret) og vridninger ("vælte" figuren).

Ved at kalde transform() på Graphics2D-objektet ændres dets koordinatsystem sådan, at alt det, der efterfølgende tegnes, bliver skaleret, drejet og vredet i henhold til transformationen. Hvis man ændrer transformationen, bør man huske den gamle (fås med getTransform()) og sætte den tilbage igen (med setTransform()), før paint() returnerer.

5.1.4 Linjetyper

Med setStroke() sætter man bredden af linjen, der skal tegnes, om linjerne skal have kantede eller afrundede endestykker og knæk, om de skal være punkterede (og hvordan).

5.1.5 Tegnekvalitet

Med setRenderingHint() sætter man forskellige vink til tegnealgoritmen: om der skal laves trappeudjævning, om hastighed eller kvalitet skal prioriteres og meget andet.

5.1.6 Videre læsning

Afsnit 12.4.2 giver et overblik over de mange klasser, der er til rådighed i Java2D.

http://java.sun.com/docs/books/tutorial/2d findes en god introduktion til Java2D.

5.2 Eksempel

I eksemplet herunder opretter vi en figur og tegner den, først almindeligt, derefter med en linjetykkelse på 2 punkter, derefter med trappeudjævning og til sidst med mere og mere rotation, skalering og vridning.

Resultatet bliver følgende figurer:

almindelig 2-pkt linjetykkelse trappeudjævning transformation x2 x3

import java.awt.*;
import java.awt.geom.*;
public class Java2DDemo extends Frame
{
  GeneralPath fig;

  AffineTransform trans;

  BasicStroke stregtype = // 2-punktsstreg med kantede ender og runde knæk
    new BasicStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND);

  public Java2DDemo()
  {
    setBackground(Color.white);

    // Lav 'smiley' - cirkel, to øjne og glad åben mund
    fig = new GeneralPath( new Ellipse2D.Float(0, 0, 100, 100) );
    fig.append( new Ellipse2D.Float(20, 20, 10, 10), false );
    fig.append( new Ellipse2D.Float(70, 20, 10, 10), false );
    fig.append( new Arc2D.Float(10,10, 80,80, 330,-120,Arc2D.CHORD), false );

    trans = AffineTransform.getScaleInstance(0.7, 0.7); // formindsk
    trans.rotate(0.3);                                  // roter
    trans.shear(0.3,0);                                 // vrid
    trans.translate(160,-50);                           // flyt til siden
  }

  public void paint(Graphics g)
  {
    Graphics2D g2 = (Graphics2D) g;              // brug Java2D

    // koordinattransformation
    AffineTransform orgTrans = g2.getTransform();// husk original transformation
    g2.translate(10,30);

    g2.draw( fig );                           // tegn almindelig
    g2.translate( 110, 0 );

    g2.setStroke( stregtype );
    g2.draw( fig );                           // tegn med 2-pkt linjetykkelse
    g2.translate( 110, 0 );

    g2.setRenderingHint( // sæt tegnevink til trappeudjævning (antialias)
      RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.draw( fig );                           // tegn med trappeudjævning


    g2.transform( trans );
    g2.draw( fig );                           // tegn med transformation

    g2.transform( trans );
    g2.draw( fig );                           // tegn med transformation  x2

    g2.transform( trans );
    g2.draw( fig );                           // tegn med transformation  x3

    g2.setTransform( orgTrans );                 // genskab orig. transformation
  }

  public static void main(String[] arg)
  {
    Java2DDemo vindue = new Java2DDemo();
    vindue.setSize(500,150);
    vindue.setVisible(true);
  }
}

5.3 Eksempel fra JDK'et

Sammen med Java følger et program, der illustrerer de fleste af mulighederne med Java2D. Det ligger i jdk1.4/demo/jfc/Java2D/Java2Demo.jar og startes ved at dobbeltklikke på jar-filen eller fra kommandolinjen skrive: java -jar Java2Demo.jar. Her ses nogle skærmbilleder:

javabog.dk  |  << forrige  |  indhold  |  næste >>  |  programeksempler  |  om bogen
http://javabog.dk/ - af Jacob Nordfalk.
Licens og kopiering under Åben Dokumentlicens (ÅDL) hvor intet andet er nævnt (71% af værket).

Ønsker du at se de sidste 29% af dette værk (362838 tegn) skal du købe bogen. Så får du pæne figurer og layout, stikordsregister og en trykt bog med i købet.