Programmering

Komme i gang med Java 2D

Java 2D API er en kjerne Java 1.2 plattform API (se Ressurser for en rekke informasjon om API og implementeringer). Implementeringer av API er tilgjengelig som en del av Java Foundation Classes (JFC) i de nåværende betaversjonene av Sun JDK for Windows NT / 95 og Solaris. Etter hvert som Java 1.2 er ferdig, bør Java 2D bli tilgjengelig på flere plattformer.

Merk at selv om Java 2D har blitt utviklet noe uavhengig av de andre delene av JFC, er det likevel en kjernedel av 1.2 AWT. Vi vil skille og peke på 2D-spesifikke funksjoner for diskusjon, men du bør huske at denne funksjonaliteten er like sentral i 1.2-grafikk som den gamle 1.0 og 1.1 AWT-støtten.

Java 2D utvider de tidligere AWT-mekanismene for å tegne 2D-grafikk, manipulere tekst og skrifttyper, laste inn og bruke bilder, og definere og håndtere farger og fargerom. Vi vil utforske disse nye mekanismene i denne og fremtidige spalter.

Et notat om nomenklatur og konvensjoner

For denne kolonnen vil min primære utviklingsplattform være en PC som kjører Windows 95 eller Windows NT. Jeg håper å gi andre plattformsspesifikke tips og triks der det er mulig, men jeg vil fokusere på Windows siden det er her jeg vil bruke mesteparten av tiden min.

Når jeg skriver et metodenavn, skal det alltid være av skjemaet metodenavn (). De etterfølgende parentesene er ment å skille dette ut som en metode. Metoden kan eller ikke ta parametere. I praksis bør konteksten alltid gjøre dette klart.

Kildekodelister vil bli gitt med linjenumre inkludert. Jeg planlegger å bruke linjenumrene til å kryssreferanse artikkelteksten og kodeoppføringene etter behov. Dette bør også gjøre det mye lettere for deg å kommentere kolonnen, hvis du velger å skrive ut en kopi. Vær imidlertid oppmerksom på at kildefilene som er koblet fra kolonnen, vil være vanlige * .java-filer (sans linjenumre) slik at du kan laste ned og utvikle dem.

Fordi jeg kommer til å skrive om mange av Media og Communications API-er de neste månedene, vil jeg sørge for at alle eksempler på koden er fornuftig i sin helhet så vel som i de enkelte delene. Jeg vil prøve å konsekvent nevne eksemplene mine og plassere dem i fornuftige pakker.

Toppen av pakkehierarkiet mitt vil være:

com.javaworld.media 

Hvert API eller emne jeg skriver om vil ha minst én underpakke under dette toppnivået. For eksempel vil all koden for denne Java 2D-artikkelen være i:

com.javaworld.media.j2d 

Så for å påkalle det første eksempelapplikasjonen på Java 2D, vil du laste ned koden, legge den i klassen din og deretter bruke:

java com.javaworld.media.j2d.Example01 

(Hvis navneområdet er for langt etter din smak, eller av en eller annen grunn, vil du bruke eksempelkoden uten å måtte bruke det fullstendige navnet, kan du bare kommentere pakkelinjen i begynnelsen av hver kildekodefil.)

Jeg vil generere en Java Archive (jar) -fil for hver artikkels eksempelkode og klassefiler. Dette arkivet vil bli gjort tilgjengelig i ressursene i hver kolonne, hvis du ønsker å laste det ned og utføre eksemplene fra arkivet.

Jeg vil også beholde en oppdatert jar-fil som inneholder all koden og klassene fra min nåværende og forrige Medieprogrammering kolonner. Denne altomfattende jar-filen vil være tilgjengelig på mitt personlige nettsted.

Et siste poeng på eksemplene: Jeg har valgt å lage hvert eksempel, med mindre jeg spesifikt bemerker noe annet, et frittstående program eller en applet. Dette vil føre til noen repetisjoner av kode fra tid til annen, men jeg føler at det best bevarer integriteten til hvert enkelt eksempel.

Nok om stevner. La oss komme i gang med programmering med Java 2D!

Graphics2D: En bedre grafikklasse

Den sentrale klassen i Java 2D API er java.awt.Graphics2D abstrakt klasse, som underklasser java.awt.Grafikk for å utvide funksjonen for gjengivelse av 2D. Grafikk2D legger til mer jevn støtte for manipulasjoner av en rekke former, og gjør tekst, linjer og alle slags andre todimensjonale former sammenlignbare når det gjelder evner og nytte.

La oss starte med et enkelt eksempel som viser hvordan du får og bruker en Grafikk2d henvisning.

001 pakke com.javaworld.media.j2d; 002003 importere java.awt. *; 004 importer java.awt.event. *; 005 006 offentlig klasse Eksempel01 utvider ramme {007 / ** 008 * Instanserer et eksempel01-objekt. 009 ** / 010 public static void main (String args []) {011 nytt eksempel01 (); 012} 013 014 / ** 015 * Eksempel01-konstruktøren vår angir rammens størrelse, legger til de 016 * visuelle komponentene og gjør dem synlige for brukeren. 017 * Den bruker en adapterklasse for å håndtere brukeren som lukker 018 * rammen. 019 ** / 020 offentlig Eksempel01 () {021 // Tittel rammen vår. 022 super ("Java 2D Eksempel01"); 023 024 // Still størrelsen på rammen. 025 setSize (400,300); 026 027 // Vi må slå på synligheten til rammen 028 // ved å sette Visible-parameteren til true. 029 setVisible (true); 030 031 // Nå vil vi være sikre på at vi disponerer ressursene på riktig måte 032 // denne rammen bruker når vinduet lukkes. Vi bruker 033 // en anonym adapter for indre klasse til dette. 034 addWindowListener (nytt WindowAdapter () 035 {public void windowClosing (WindowEvent e) 036 {disponere (); System.exit (0);} 037} 038); 039} 040 041 / ** 042 * Malingsmetoden gir den virkelige magien. Her 043 * kastet grafikkobjektet til Graphics2D for å illustrere 044 * at vi kan bruke de samme gamle grafikkegenskapene med 045 * Graphics2D som vi er vant til å bruke med Grafikk. 046 ** / 047 offentlig tom maling (grafikk g) {048 // Slik tegnet vi en firkant med bredden 049 // på 200, høyden på 200 og startet på x = 50, y = 50. 050 g.setColor (Color.red); 051 g. DrawRect (50 50 200 200); 052053 // La oss sette Color til blått og deretter bruke Graphics2D 054 // objektet til å tegne et rektangel, forskjøvet fra firkanten. 055 // Så langt har vi ikke gjort noe ved hjelp av Graphics2D som 056 // vi ikke kunne gjøre med Grafikk. (Vi bruker faktisk 057 // ved hjelp av Graphics2D-metoder arvet fra Graphics.) 058 Graphics2D g2d = (Graphics2D) g; 059 g2d.setColor (Color.blue); 060 g2d.drawRect (75,75,300,200); 061} 062} 

Når du kjører Eksempel01, bør du se et rødt firkant og blå rektangel, som vist i figuren nedenfor. Merk at det er et kjent ytelsesproblem med Windows NT / 95-versjonen av JDK 1.2 Beta 3 (den nyeste 1.2-versjonen fra denne kolonnen). Hvis dette eksemplet er smertefullt tregt på systemet ditt, må du kanskje omgå feilen som dokumentert i JavaWorldJava Tips 55 (Se Ressurser nedenfor for dette tipset).

Vær oppmerksom på at akkurat som du ikke instantierer direkte a Grafikk objekt, instanserer du ikke a Grafikk2D objekt heller. Snarere konstruerer Java-kjøretiden et gjengivelsesobjekt og sender det til maling() (linje 047 i eksempel01-kodelisten), og på Java 1.2-plattformer og utover implementerer dette objektet Grafikk2D abstrakt klasse også.

Så langt har vi ikke gjort noe spesielt med våre 2D-grafikkfunksjoner. La oss legge til litt kode på slutten av forrige eksempel maling() metode og få inn flere funksjoner som er nye for Java 2D (eksempel02):

001 / ** 002 * Her bruker vi nye Java 2D API-funksjoner som affine 003 * transformasjoner og Shape-objekter (i dette tilfellet en generisk 004 * one, GeneralPath). 005 ** / 006 offentlig tom maling (grafikk g) {007 g.setColor (Color.red); 008 g. DrawRect (50 50 200 200); 009010 Grafikk2D g2d = (Grafikk2D) g; 011 g2d.setColor (Color.blue); 012 g2d.drawRect (75,75,300,200); 013 014 // La oss nå tegne et annet rektangel, men denne gangen, la oss 015 // bruke en GeneralPath til å spesifisere det segment for segment. 016 // Videre skal vi oversette og rotere dette 017 // rektangelet i forhold til enhetsområdet (og dermed til 018 // de to første firkantene) ved hjelp av en AffineTransform. 019 // Vi vil også endre fargen. 020 GeneralPath-sti = ny GeneralPath (GeneralPath.EVEN_ODD); 021 path.moveTo (0.0f, 0.0f); 022 path.lineTo (0.0f, 125.0f); 023 path.lineTo (225.0f, 125.0f); 024 path.lineTo (225.0f, 0.0f); 025 path.closePath (); 026 027 AffineTransform at = new 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 (Farge grønn); 034 g2d.fill (sti); 035} 

Merk at siden Generelt vei ligger i java.awt.geom pakken, må vi være sikre på at vi også legger til en importlinje:

importer java.awt.geom. *; 

Utgangen fra eksempel02 er vist i følgende figur.

Java 2D tillater spesifikasjon av vilkårlige former ved hjelp av java.awt.Shape grensesnitt. En rekke standardformer som rektangler, polygoner, 2D-linjer osv. Implementerer dette grensesnittet. En av de mest interessante av disse når det gjelder fleksibilitet er java.awt.geom.GeneralPath.

Generelt veis lar deg beskrive en sti med et vilkårlig antall kanter og en potensielt ekstremt kompleks form. I eksempel02 har vi opprettet et rektangel (linjene 020-025), men vi kunne like gjerne ha lagt til en annen side eller sider for å lage en femkant, eller heptagon, eller en annen flersidig polygon. Vær også oppmerksom på at i motsetning til standard Grafikk kode, tillater Java 2D oss å spesifisere koordinater ved hjelp av flytende tall i stedet for heltall. CAD-leverandører i verden, glede seg! Faktisk støtter Java 2D heltall, dobbelt, og flytende aritmetikk mange steder.

Du la sannsynligvis også merke til at da vi opprettet banen, passerte vi en parameter, GeneralPath.EVEN_ODD, inn i konstruktøren (linje 020). Denne parameteren representerer en svingete regel som forteller gjengiveren hvordan man bestemmer innsiden av formen som er spesifisert av vår vei. Se Java 2D javadoc-dokumentasjonen som det vises til i Resources for mer om Java 2D-viklingsregler.

Den andre store innovasjonen i eksempel02 dreier seg om bruken av en java.awt.geom.AffineTransforms (linje 027-031). Jeg overlater detaljene til slike transformasjoner til leseren (se Ressurser for artikler som diskuterer dette mer detaljert), men det er nok å si at AffineTransforms lar deg bruke en hvilken som helst Java 2D-grafikk for å oversette (flytte) den, rotere den, skalere den, skjære den eller utføre kombinasjoner av disse manipulasjonene.

Nøkkelen til AffineTransform ligger i begrepet Enhetsplass og Brukerplass. Device Space er det området der grafikken skal gjengis på skjermen. Dette er analogt med koordinatene som brukes når man lager vanlig AWT-stil Grafikk-basert 2D-grafikk. User Space er imidlertid et oversettbart, roterbart koordinatsystem som kan betjenes av en eller flere AffineTransforms.

Device Space og User Space koordinatsystemer overlapper i utgangspunktet, med opprinnelsen øverst til venstre på gjengivelsesflaten (her en ramme). Den positive x-aksen beveger seg rett fra opprinnelsen, mens den positive y-aksen beveger seg nedover.

Etter den første transformasjonen i eksempel 02 (linjene 028 og 029) har koordinatsystemet User Space blitt rotert 22,5 grader mot klokken i forhold til enhetsområdet. Begge deler fortsatt samme opprinnelse. (Vær oppmerksom på at rotasjoner er spesifisert i radianer, med -PI / 8 radianer som tilsvarer -22,5 grader eller 22,5 grader CCW.) Hvis vi skulle stoppe her og tegne rektangelet, ville det roteres for det meste ut av synsfeltet vårt i applikasjon Ramme.

Vi bruker deretter en andre transformasjon (linje 030 og 031), denne en oversettelse, etter at rotasjonen er fullført. Dette flytter User Space-koordinatsystemet i forhold til Device Space, og flytter det ned 200,0 (float) enheter og høyre 50,0 (float) enheter.

Når vi fyller ut det grønne rektangelet, blir det oversatt og rotert i forhold til enhetsområdet.

Av Bezier og høyere ordnede kurver

Nå som vi har undersøkt hvordan transformasjoner kan brukes til å manipulere grafiske objekter, la oss undersøke hvordan vi bygger komplekse og interessante vilkårlige former.

Kurver brukes gjennom matematikk og datagrafikk for å tilnærme komplekse former ved å bruke et endelig, veldefinert (og ideelt sett lite) antall matematiske punkter. Mens standard AWT ikke direkte støttet tegning med vilkårlige kurver tidligere (Java 1.0- eller 1.1-plattformer), legger Java 2D til innebygd støtte for kurver av første, andre og tredje orden. Du kan tegne kurver med to sluttpunkter og null, en eller to kontrollpunkter. Java 2D beregner første- og andreordens kurver ved hjelp av lineære og kvadratiske formler og kubiske eller tredje ordens kurver ved hjelp av Bezier-kurver.

(Bezier-kurver er en type parametrisk polynomkurve som har noen svært ønskelige egenskaper knyttet til beregning av lukkede kurver og overflater. De brukes i mange grafiske applikasjoner. Se ressursene for mer informasjon om bruk av parametriske polynomer og Bezier-kurver i datagrafikk.) The Generelt vei metoder som tegner hver av disse kurvene er:

  • lineTo () for rette segmenter (spesifiser bare sluttpunkter)
  • quadTo () for kvadratiske kurver (spesifiser ett kontrollpunkt)
  • curveTo () for tredjeordens kurver (spesifiser to kontrollpunkter, tegnet med kubisk Bezier-kurve)
$config[zx-auto] not found$config[zx-overlay] not found