Programmering

Kom godt i gang med Java 2D

Java 2D API er en grundlæggende Java 1.2-platform API (se Ressourcer for en række oplysninger om API'en og dens implementeringer). Implementeringer af API er tilgængelige som en del af Java Foundation Classes (JFC) i de nuværende betaudgivelser af Sun JDK til Windows NT / 95 og Solaris. Da Java 1.2 er afsluttet, skal Java 2D blive tilgængelig på flere platforme.

Bemærk, at selvom Java 2D er blevet udviklet noget uafhængigt af de andre dele af JFC, er det alligevel en kerne del af 1.2 AWT. Vi skelner og påpeger 2D-specifikke funktioner til diskussion, men du skal huske, at denne funktionalitet er lige så central for 1.2-grafik som den gamle 1.0 og 1.1 AWT-understøttelse.

Java 2D udvider de tidligere AWT-mekanismer til at tegne 2D-grafik, manipulere tekst og skrifttyper, indlæse og bruge billeder og definere og håndtere farver og farverum. Vi vil udforske disse nye mekanismer i denne og fremtidige kolonner.

En note om nomenklatur og konventioner

I denne kolonne vil min primære udviklingsplatform være en pc, der kører Windows 95 eller Windows NT. Jeg håber at give andre platformsspecifikke tip og tricks, hvor det er muligt, men jeg vil fokusere på Windows, da det er her, jeg bruger det meste af min tid.

Når jeg skriver et metodenavn, skal det altid have formen metodenavn (). De bageste parenteser er beregnet til at skille dette ud som en metode. Metoden kan muligvis ikke tage parametre. I praksis skal sammenhængen altid gøre dette klart.

Kildekodelister vil blive givet med inkluderede linjenumre. Jeg planlægger at bruge linjenumrene til at krydshenvise artikelteksten og kodelisterne efter behov. Dette skulle også gøre det meget lettere for dig at kommentere kolonnen, hvis du vælger at udskrive en kopi. Bemærk dog, at de kildefiler, der er linket fra kolonnen, vil være almindelige * .java-filer (sans linjenumre), så du kan downloade og udvikle dem.

Fordi jeg vil skrive om mange af Media and Communications API'erne i de kommende måneder, vil jeg sørge for, at hele prøvekoden giver mening som helhed såvel som i dens individuelle dele. Jeg vil forsøge konsekvent at navngive mine eksempler og placere dem i fornuftige pakker.

Toppen af ​​mit pakkehierarki vil være:

com.javaworld.media 

Hver API eller hvert emne, som jeg skriver om, vil have mindst en underpakke under dette topniveau. For eksempel vil al koden til denne Java 2D-artikel være i:

com.javaworld.media.j2d 

Så for at påberåbe det første eksempel på Java 2D, skal du downloade koden, lægge den i din klassesti og derefter bruge:

java com.javaworld.media.j2d.Example01 

(Hvis navneområdet er for langt efter din smag, eller af en anden grund, du vil bruge eksempelkoden uden at skulle bruge det fuldt kvalificerede navn, skal du blot kommentere pakkelinjen i begyndelsen af ​​hver kildekodefil.)

Jeg genererer en Java Archive (jar) -fil til hver artikels eksempelkode og klassefiler. Dette arkiv vil blive gjort tilgængeligt i ressourcerne i hver kolonne, hvis du ønsker at downloade det og udføre eksemplerne fra arkivet.

Jeg vil også opbevare en opdateret jar-fil, der indeholder alle koder og klasser fra min nuværende og forrige Medieprogrammering kolonner. Denne altomfattende jar-fil vil være tilgængelig på mit personlige websted.

Et sidste punkt på eksemplerne: Jeg har valgt at lave hvert eksempel, medmindre jeg specifikt bemærker andet, en enkeltstående applikation eller applet. Dette vil medføre gentagelse af kode fra tid til anden, men jeg føler, at det bedst bevarer integriteten i hvert enkelt eksempel.

Nok om konventioner. Lad os komme i gang med programmering med Java 2D!

Graphics2D: En bedre grafikklasse

Den centrale klasse inden for Java 2D API er java.awt.Grafik2D abstrakt klasse, som underklasser java.awt.Grafik at udvide 2D-gengivelsesfunktionalitet. Grafik2D tilføjer mere ensartet understøttelse af manipulationer af en række forskellige former, hvilket i virkeligheden gør tekst, linjer og alle mulige andre todimensionale former sammenlignelige i deres evner og anvendelighed.

Lad os starte med et simpelt eksempel, der viser, hvordan du får og bruger en Grafik2d reference.

001 pakke com.javaworld.media.j2d; 002 003 import java.awt. *; 004 import java.awt.event. *; 005 006 offentlig klasse Eksempel01 udvider ramme {007 / ** 008 * Instantierer et eksempel01-objekt. 009 ** / 010 public static void main (String args []) {011 nyt eksempel01 (); 012} 013 014 / ** 015 * Vores eksempel01-konstruktør indstiller rammens størrelse, tilføjer de 016 * visuelle komponenter og gør dem derefter synlige for brugeren. 017 * Det bruger en adapterklasse til at håndtere brugeren, der lukker 018 * rammen. 019 ** / 020 offentlig Eksempel01 () {021 // Titel vores ramme. 022 super ("Java 2D Eksempel01"); 023 024 // Indstil størrelsen på rammen. 025 setSize (400.300); 026 027 // Vi skal aktivere synligheden af ​​vores ramme 028 // ved at indstille den synlige parameter til sand. 029 setVisible (sand); 030 031 // Nu vil vi være sikre på, at vi bortskaffer ressourcer korrekt 032 // denne ramme bruger, når vinduet lukkes. Vi bruger 033 // en anonym adapter til den indre klasse til dette. 034 addWindowListener (new WindowAdapter () 035 {public void windowClosing (WindowEvent e) 036 {disponere (); System.exit (0);} 037} 038); 039} 040 041 / ** 042 * Malingsmetoden giver den ægte magi. Her kaster vi 043 * grafikobjektet til Graphics2D for at illustrere 044 *, at vi kan bruge de samme gamle grafikfunktioner med 045 * Graphics2D, som vi er vant til at bruge sammen med Grafik. 046 ** / 047 offentlig hulmaling (grafik g) {048 // Sådan tegner vi en firkant med bredden 049 // på 200, højden på 200 og starter ved x = 50, y = 50. 050 g.setColor (farve.rød); 051 g.drawRect (50,50,200,200); 052053 // Lad os indstille farven til blå og derefter bruge grafik2D 054 // objektet til at tegne et rektangel, forskudt fra firkanten. 055 // Indtil videre har vi ikke gjort noget ved hjælp af Graphics2D, som 056 // vi ikke kunne gøre ved hjælp af Graphics. (Vi bruger faktisk 057 // ved hjælp af Graphics2D-metoder arvet fra Graphics.) 058 Graphics2D g2d = (Graphics2D) g; 059 g2d.setColor (farve.blå); 060 g2d.drawRect (75,75,300,200); 061} 062} 

Når du udfører eksempel01, skal du se et rødt firkantet og blåt rektangel som vist i nedenstående figur. Bemærk, at der er et kendt ydeevneproblem med Windows NT / 95-versionen af ​​JDK 1.2 Beta 3 (den nyeste 1.2-version fra denne kolonne). Hvis dette eksempel er smertefuldt langsomt på dit system, skal du muligvis omgå fejlen som dokumenteret i JavaWorldJava Tip 55 (Se Ressourcer nedenfor for dette tip).

Bemærk, at ligesom du ikke direkte instantierer a Grafik objekt, du instantierer ikke a Grafik2D gør heller ikke noget imod. I stedet konstruerer Java-runtime et gengivelsesobjekt og sender det til maling() (linje 047 i eksempel01-kodelisten), og på Java 1.2-platforme og derover implementerer dette objekt Grafik2D abstrakt klasse også.

Indtil videre har vi ikke gjort noget særligt specielt med vores 2D-grafikfunktioner. Lad os tilføje nogle kode i slutningen af ​​vores tidligere eksempler maling() metode og få flere funktioner nye til Java 2D (eksempel02):

001 / ** 002 * Her bruger vi nye Java 2D API-funktioner såsom affine 003 * -transformer og Shape-objekter (i dette tilfælde en generisk 004 * one, GeneralPath). 005 ** / 006 ugyldig maling (grafik g) {007 g.setColor (farve.rød); 008 g.drawRect (50,50,200,200); 009 010 Grafik2D g2d = (Grafik2D) g; 011 g2d.setColor (farve.blå); 012 g2d.drawRect (75,75,300,200); 013 014 // Lad os nu tegne et andet rektangel, men denne gang, lad os 015 // bruge en GeneralPath til at specificere det segment for segment. 016 // Desuden skal vi oversætte og rotere dette 017 // rektangel i forhold til Enhedsområdet (og dermed til 018 // de første to firkanter) ved hjælp af en AffineTransform. 019 // Vi ændrer også farve. 020 GeneralPath-sti = ny GeneralPath (GeneralPath.EVEN_ODD); 021 path.moveTo (0.0f, 0.0f); 022 sti.lineTo (0,0f, 125,0f); 023 path.lineTo (225.0f, 125.0f); 024 path.lineTo (225.0f, 0.0f); 025 sti.closePath (); 026 027 AffineTransform ved = ny AffineTransform (); 028 ved. SetToRotation (-Math.PI / 8.0); 029 g2d.transform (at); 030 at.setToTranslation (50.0f, 200.0f); 031 g2d.transform (at); 032 033 g2d.setColor (Farvegrøn); 034 g2d.fill (sti); 035} 

Bemærk, at siden Generelt sti er placeret i java.awt.geom pakke, skal vi også være sikre på, at vi tilføjer en importlinje:

import java.awt.geom. *; 

Outputtet fra eksempel02 er vist i den følgende figur.

Java 2D muliggør specifikation af vilkårlige former ved hjælp af java.awt.Shape interface. En række standardformer som rektangler, polygoner, 2D-linjer osv. Implementerer denne grænseflade. En af de mest interessante af disse med hensyn til fleksibilitet er java.awt.geom.GeneralPath.

Generelt stis lad dig beskrive en sti med et vilkårligt antal kanter og en potentielt ekstremt kompleks form. I eksempel02 har vi oprettet et rektangel (linjer 020-025), men vi kunne lige så let have tilføjet en anden side eller sider for at lave en femkant eller heptagon eller en anden flersidet polygon. Bemærk også, at i modsætning til standard Grafik kode, giver Java 2D os mulighed for at specificere koordinater ved hjælp af flydende numre i stedet for heltal. CAD-leverandører i verden, glæd dig! Faktisk understøtter Java 2D heltal, dobbeltog flydende aritmetik mange steder.

Du bemærkede sandsynligvis også, at da vi oprettede stien, passerede vi en parameter, GeneralPath.EVEN_ODD, ind i konstruktøren (linje 020). Denne parameter repræsenterer en snoede regel der fortæller rendereren, hvordan man bestemmer indersiden af ​​den form, der er angivet af vores sti. Se Java 2D javadoc-dokumentationen, der henvises til i ressourcerne, for mere om Java 2D-viklingsregler.

Den anden store innovation i eksempel02 drejer sig om brugen af ​​en java.awt.geom.AffineTransforms (linje 027-031). Jeg overlader det specifikke ved sådanne transformationer til læseren (se Ressourcer til artikler, der diskuterer dette mere detaljeret), men det er tilstrækkeligt at sige, at AffineTransforms giver dig mulighed for at betjene enhver Java 2D-grafik for at oversætte (flytte) den, rotere den, skalere den, forskyde den eller udføre kombinationer af disse manipulationer.

Nøglen til AffineTransform ligger i begrebet Enhedsplads og Brugerplads. Enhedsplads er det område, hvor grafikken gengives på skærmen. Dette er analogt med de koordinater, der bruges, når man opretter regelmæssig AWT-stil Grafik-baseret 2D-grafik. User Space er dog et oversætteligt, roterbart koordinatsystem, der kan betjenes af en eller flere AffineTransforms.

Device Space- og User Space-koordinatsystemer overlapper oprindeligt med oprindelsen øverst til venstre på gengivelsesfladen (her en ramme). Den positive x-akse bevæger sig lige fra oprindelsen, mens den positive y-akse bevæger sig nedad.

Efter den første transformation i eksempel 02 (linje 028 og 029) er brugerrumskoordinatsystemet roteret 22,5 grader mod uret i forhold til enhedens rum. Begge deler stadig den samme oprindelse. (Bemærk, at rotationer er specificeret i radianer, med -PI / 8 radianer, der svarer til -22,5 grader eller 22,5 grader CCW.) Hvis vi skulle stoppe her og tegne rektanglet, ville det for det meste blive drejet ud af vores synsfelt i Ansøgning Ramme.

Dernæst anvender vi en anden transformation (linie 030 og 031), denne en oversættelse, efter at rotationen er afsluttet. Dette flytter User Space-koordinatsystemet i forhold til Device Space og flytter det ned 200,0 (float) enheder og højre 50,0 (float) enheder.

Når vi udfylder det grønne rektangel, oversættes det og roteres i forhold til enhedsområdet.

Af Bezier og højere ordnede kurver

Nu hvor vi har undersøgt, hvordan transformationer kan bruges til at manipulere grafiske objekter, lad os genoverveje, hvordan vi bygger komplekse og interessante vilkårlige former.

Kurver bruges i hele matematik og computergrafik til at tilnærme komplekse former ved hjælp af et endeligt, veldefineret (og ideelt lille) antal matematiske punkter. Mens standard AWT ikke tidligere understøttede tegning med vilkårlige kurver (Java 1.0- eller 1.1-platforme), tilføjer Java 2D indbygget understøttelse til kurver i første, anden og tredje orden. Du kan tegne kurver med to slutpunkter og nul, en eller to kontrolpunkter. Java 2D beregner første- og andenordens kurver ved hjælp af lineære og kvadratiske formler og kubiske eller tredje ordens kurver ved hjælp af Bezier-kurver.

(Bezier-kurver er en type parametrisk polynomial kurve, der har nogle meget ønskelige egenskaber relateret til beregning af lukkede kurver og overflader. De bruges i adskillige grafiske applikationer. Se ressourcerne for mere information om brugen af ​​parametriske polynomer og Bezier-kurver i computergrafik.) Generelt sti metoder, der tegner hver af disse kurver, er:

  • lineTo () for lige segmenter (angiv kun slutpunkter)
  • quadTo () til kvadratiske kurver (angiv et kontrolpunkt)
  • curveTo () for tredjeordens kurver (angiv to kontrolpunkter, tegnet ved hjælp af kubisk Bezier-kurve)