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:
Klasser til en række geometriske grundfigurer, såsom linjer, kurver, rektangler, ellipser og mekanismer til at tegne næsten enhver ønskelig geometrisk form.
Transformationer (skalering, rotering, vridning) af figurer, tekster og billeder.
Halvgennemsigtig tegning (hvor det, der var bag ved det tegnede, stadig kan skimtes).
Trappeudjævning (udjævnede farveovergange, eng.: antialiasing).
Mekanismer til at afgøre, om et punkt er inden eller uden for en vilkårlig geometrisk figur, tekst eller billede (f.eks. klik med musen).
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);
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:
Rektangler - Rectangle2D og RoundRectangle2D
Linjer - Line2D (en ret linje), CubicCurve2D (en linje, der er buet efter et ankerpunkt) og QuadCurve2D (en linje, der er buet efter to ankerpunkter)
Ellipse2D og Arc2D (buestykke)
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).
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 finder foreningsmængden af A og B
intersect finder fællesmængden af A og B
subtract trækker fællesmængden af A og B fra A
exclusiveOr finder foreningsmængden af A og B, men fjerner fællesmængden
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.
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.
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).
Med setRenderingHint() sætter man forskellige vink til tegnealgoritmen: om der skal laves trappeudjævning, om hastighed eller kvalitet skal prioriteres og meget andet.
Afsnit 12.4.2 giver et overblik over de mange klasser, der er til rådighed i Java2D.
På http://java.sun.com/docs/books/tutorial/2d findes en god introduktion til Java2D.
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); } }
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