Klasa Graphics

Digresija: JBuilder na CD-u sadrzi 3--dnevnu probnu instalacionu verziju JBuilder EnterpriseEdition za Windows, Linux, Solaris. Ta verzija ce preci u besplatan PersonalEdition alat nakon 30 dana.
Dobijanje licencnog kljuca pre upotrebe alata JBuilder-a je preko Web strane http://www.borland.com/jbuilder/keys/jb6_ent_steps.html

Koordinatni sistem
Java koristi standardni, dvodimenzionalni sistem za računarsku grafiku. Prvi vidljivi piksel u gornjem levom uglu apletove pozadine je tačka (0, 0). Koordinate se povecavaju prema desno i nadole.

Crtanje se u Javi obavlja pomocu objekata klase java.awt.Graphics.
Graficki objekt se daje kao argument metodi paint(Graphics g) koju klasa java.applet.Applet nasledjuje od klase java.awt.Container.  Sve sto bude receno  o crtanju u apletima vazi i za objekte kao sto su paneli, okviri, dugmici, pozadine itd.
Iscrtavanje se uglavnom obavlja u metodu paint(). Iscrtavanje se može izvoditi direktno na apletu ili na radnoj površini koje će zbog svojih specifičnosti biti obrađeno kasnije.
Svaki objekt tipa Graphics ima svoj vlastiti koordinatni sistem i metode za crtanje stringova, linija, pravougaonika, krugova, poligona i tako dalje. Crtanje u Javi počinje od pojedinačnog objekta tipa Graphics. Pristup tom objektu ostvaruje se metodom paint(Graphics g) u apletu..
Primer poziva metode za crtanje:
g.drawString("Hello World", 0, 50)
--------------------------------------------------------------------------------

Iscrtavanje linija

Za crtanje prave linije poziva se metod drawline() cija  sintaksa je:

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

Poziva se ovako:

g.drawLine(x1, y1, x2, y2)

Pri tome su (x1, y1) i (x2, y2) krajnje tacke linije, a g je objekt tipa Graphics pomocu kog se iscrtava linija.
Primer koji iscrtava liniju dijagonalno preko appleta.

import java.applet.*;
import java.awt.*;

public class Dijagonala extends Applet {

 public void paint(Graphics g) {

    g.drawLine(0, 0, this.getSize().width, this.getSize().height);

 }

}

<APPLET code="Dijagonala.class"
HEIGHT="200" WIDTH="200">
</APPLET>
 

Klasa Graphics sadrži nekoliko metoda za iscrtavanje i sve one imaju ograničenja poput:
  debljina linije je debljina tačke
  objekti se iscrtavaju u tekućoj boji
No, metodi su sasvim dovoljni za dijagrame, isticanje teksta, jednostavne animacije,...

Primer koji iscrtava na apletu tanku liniju od pozicije koordinatnog početka do pozicije koja je od nje udaljena 100 tačaka desno i 50 tačaka nadole. Takođe u primeru se vrši i scrtavanje deblje linije, tako što se uz osnovnu liniju iscrta još nekoliko linija.

tanka i deblja linija

   import java.awt.*;
   import java.applet.*;

   public class TankaDebelaLinija extends Applet {

 public void paint(Graphics g) {

    g.drawLine(0, 0, 100, 50);  /* iscrtava osnovnu liniju od (0,0) do (100, 50) */

   g.setColor(new Color(255,0,0)); /* metod obradjen u 5. nastavku-metod koji podesava tekucu
                                       boju objekta pre njegovog iscrtavanja; zadaje se kao triplet intenziteta
                                       boja u RGB modelu */

  g.drawLine (50,75,200,25);
  g.drawLine (50,75,200,26);  /* druga naredba se koristi da pojaca ispis iz prethodne naredbe*/

 g.setColor(new Color(0,255,0)); /* zelena*/

  for (int y1=120; y1<130; y1++)
      g.drawLine(100, y1, 200, y1+20); /* uz osnovnu linju iscrtavanje se pojacava sa dodatnih  9 linija*/
 }

}
 

Primer koji kreira animaciju u formi linije koja rotira oko centra (120,120) i iscrtava krug.
Matematički model zahteva da se uoči da pri ma kom uglu, poluprečnik se izdvaja kao hipotenuza
trougla čije katete se prostiru od centra kruga do x, y koordinata neke tačke na kružnici.
 
 

trag rotacije

x= (int) (java.lang.Math.cos(ugao)*100) + 120; /* 100=duzina linije, poluprecnika;
                                                                                   (120, 120) koordinate centra*/
 

   import java.awt.*;
   import java.applet.*;

   public class TragRotacije extends Applet {

          Color bela=new Color(180,255,255); /* nije bas (255,255,255) ali ostavlja trag*/
          Color crna=new Color(0,0,0);
          public void paint(Graphics g) {
            int x,y; /*tacke granice kruga*/
           double ugao=0;

           while(ugao < 6.28)   /* Java meri uglove u radijanima, 2PI radijana za 360 stepeni;
                while(ugao < 2*Math.PI) */ {
               x= (int) (java.lang.Math.cos(ugao)*100) + 120;
                 y= (int) (java.lang.Math.sin(ugao)*100) + 120;
                 g.setColor(crna);
                g.drawLine(120,120,x,y);  /* iscrtava polaznu liniju */

                  /*prazna petlja za usporeni prikaz*/
                    for(int pauza=0; pauza <20000; pauza ++)  ;

                 g.setColor(bela);
                 g.drawLine(120,120,x,y);  /* novi polozaj*/
                 ugao=ugao+0.01;
            }
            g.setColor(crna);
            g.drawLine(120,120,220,120); /* ponovo se iscrtava da prikaze krajnji polozaj*/

     }

}

 --------------------------------------------------------------------------------

Crtanje pravougaonika

Pravougaonik se iscrtava pomocu objekta g iz klase Graphics i metode drawRect() cija je sintaksa:

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

Poziva se ovako:

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

Prva dva argumenta su koordinate gornjeg levog ugla pravougaonika, dok su ostala dva njegova sirina i visina.

Primer koji  iscrtava pravougaonik oko appleta.

import java.applet.*;
import java.awt.*;

public class Pravougaonik extends Applet {

  public void paint(Graphics g) {

    g.drawRect(0, 0, this.getSize().width - 1, this.getSize().height - 1);

  }

}

Znamo da getSize().width je sirina pravougaonika, a getSize().height njegova visina.
Zasto se onda pravougaonik iscrtava samo do getSize().height-1 i getSize().width-1?

Zato jer se levi gornji ugao nalazi u tacki (0, 0), a ne u (1, 1). To znaci da aplet velicine 100 x 200 piksela ukljucuje tacke s x-koordinatama izmedju 0 i 99, a ne izmedju 0 i 100. Slicno, y-koordinate su izmedju 0 i 199 ukljucivo, a ne izmedju 0 i 200.

Za crtanje kvadrata ne postoji posebna drawSquare() metoda. Kvadrat je pravougaonik jednakih stranica.
--------------------------------------------------------------------------------

Iscrtavanje ispunjenog  pravougaonika







Metoda drawRect() crta prazan pravougaonik. Ako se zeli crtati kao  ispunjen, postoji metod
fillRect() cija je sintaksa:

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

Primer koji  crta ispunjeni pravougaonik u centru apleta. Mora se razlikovati velicina pravougaonika od velicine appleta.

import java.applet.*;
import java.awt.*;

public class PopuniCentriraj extends Applet {

  public void paint(Graphics g) {

    int appletVisina = this.getSize().height;
    int appletSirina  = this.getSize().width;
    int rectVisina   = appletVisina/3;
    int rectSirina    = appletSirina/3;
    int rectTop      = (appletVisina - rectVisina)/2;
    int rectLeft     = (appletSirina - rectSirina)/2;

    g.fillRect(rectLeft, rectTop, rectSirina-1, rectVisina-1);

  }

}

<APPLET code="PopuniCentriraj.class"
HEIGHT="50" WIDTH="40">
</APPLET>
 

Primer koji iscrtava pravougaonik tanjih i ispod njega pravougaonik debljih ivica. (Metod drawRect iscrtava tanke linije kao stranice).
Unutar pravougaonika ispisati stringove Prvi, Drugi pojacanim fontom velicine 14pt tipa SansSerif.

  Ako se zele deblje linije za ivice, onda se moze upotrebiti petlja i iscrtati jedan ispunjeni pravougaonik unutar drugog.

import java.applet.*;
import java.awt.*;

public class Pravougaonik2 extends Applet {
   Color crvena=new Color(0,255,255);
   Color zuta=new Color(255,255,0);
   Color crna=new Color(0,0,0);
   Font niska=new Font("SansSerif", Font.BOLD, 14);

  public void paint(Graphics g) {

     g.setFont(niska); /* postavlja se opis fonta za tekuci objekat */
     g.setColor (crvena); /* tekuca boja objekta */

      /* iscrtava se 5 uzastopnih pravougaonika; pocev od pravougaonika (50,50, 150, 75);
        uzastopni pravougaonici su 2 piksel manji, a pocinju 1 piksel unutra i nadole, te se i od sirine    i od duzine oduzima 2*i */
      for (int i=0; i<5; i++)
          g.drawRect(50+i, 50+i, 150-2*i, 75-2*i);

     g.setColor(crna); /* postavlja se boja ispisa niske Prvi u 1. pravougaoniku */
     g.drawString("Prvi",80,90);

     g.setColor(crvena); /* postavlja se boja ispisa pravougaonika 2 koji se nalazi  ispod pravougaonika 1*/
     g.fillRect(50, 150,200,100);

      g.setColor(zuta); /* menja se unutrasnja boja, tj. ako je unutrasnja boja ista kao i pozadina, onda se barem vidi okvir pravougaonika*/
     g.fillRect(60, 160,180,80);
 

     g.setColor(crna); /* postavlja se boja ispisa niske Drugi u 2. pravougaoniku */
     g.drawString("Drugi",100,200);

  }

}
 

--------------------------------------------------------------------------------

Brisanje pravougaonika

Nacrtani pravougaonik moze se izbrisati metodom clearRect() cija je sintaksa:
public abstract void clearRect(int x,
                               int y,
                               int width,
                               int height)

Primer koji koristi metod clearRect() da bi prikazao bljesak pravougaonika na ekranu.

import java.applet.*;
import java.awt.*;

public class Blink extends Applet {

  public void paint(Graphics g) {

    int appletH = this.getSize().height;
    int appletW  = this.getSize().width;
    int rectH   = appletH/3;
    int rectW    = appletW/3;
    int rectTop      = (appletH - rectH)/2;
    int rectLeft     = (appletW - rectW)/2;

    for (int i=0; i < 1000000; i++) {
      g.fillRect(rectLeft, rectTop, rectW-1, rectH-1);
      g.clearRect(rectLeft, rectTop, rectW-1, rectH-1);
    }

  }

}

Ovo nije nacin kako se u praksi radi animacija, no to je privremeno resenje  dok se ne nauci Java mehanizam rada sa nitima (thread).
--------------------------------------------------------------------------------

Elipse i kruznice

Elipse i kruznice crtaju se pomocu metode drawOval(), a pune pomocu metode fillOval() cije su sintaksne signature:
public abstract void drawOval(int x,
                              int y,
                              int width,
                              int height)

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

Argumenti ovih metoda predstavljaju koordinate gornjeg levog ugla, sirinu i visinu pravougaonika kom je elipsa upisana.

Nema posebne metode za crtanje kruznice. Kruznicu smatrati je elipsom upisanom u kvadrat.
 

Primer apleta koji iscrtava elipsu i krug zajedno sa opisanim pravougaonicima oko njih.

elipsa i krug

import java.applet.*;
import java.awt.*;

public class ElipsaKrugPravougaonik extends Applet {

  Color siva= new Color(160,160,160);
  Color crna= new Color(0,0,0);

  public void paint(Graphics g) {

      g.drawRect(10,10,150,100);  /* pravougaonik 1*/
     g.setColor(siva);
     g.fillOval(10,10,150,100); /* ispunjena siva elipsa u pravougaoniku 1; stvarni parametri identicni
        kao u pozivu metoda drawRect */

    g.fillRect(180,40, 100, 100);  /* sivi kvadrat */
   g.setColor(crna);
   g.fillOval(180,40,100,100); /*crni krug u sivom kvadratu*/
   g.setColor(siva);
   g.fillOval(200,60,60,60);  /* sivi krug u crnom krugu */

  }

}
 
 
 

Java sadrzi metode za crtanje praznih i ispunjenih lukova. Oni su izvedeni iz metoda za crtanje elipsi, ali imaju dva dodatna parametra - pocetak luka i velicinu ugla luka. To su metode drawArc() i fillArc(). Ponasaju se slicno kao drawOval() i fillOval().
Signature:

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

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

U pravougaonik se upisuje najveci moguci luk. Lokacija luka od 0 stepeni, kao i smer, tj. odgovor da li je luk nacrtan u smeru kazaljke na satu ili suprotnom ne zavisi od platforme.
Na primer, poziv
    g.fillArc(10,10,100,100,0,90)
iscrtava isecak kruga (width=height=100) ciji precnik je 100 tacaka i gornji levi ugao opisanog
kvadrata je na poziciji 10,10. Isecak ima formu prve cetvrtine kruga.
Uglovi luka se zadaju u celobrojnim vrednostima stepena, a ne u radijanima (koji su argumenti trigonomterijskih funkcija). 0 stepeni bi bilo na vrednosti 3 casovnika,...i uglovi se mere suprotno kretanju kazaljki na satu. Ako se zeli zadavanje uglova u smeru kretanaj kazaljke na satau, onda se koriste negativne vrednosti uglova.

Napisati aplet koji iscrtava sledecu sliku:

lukovi

import java.applet.*;
import java.awt.*;
 

public class Lukovi extends Applet {

  public void paint(Graphics g) {
        g.fillArc(10,10,100,100, 0, 90);  /* ispunjena prva cetvrtina kruga */
        g.drawArc(10,10,100,100,90,180); /* u istom krugu, bez granice druge cetvrtine*/
        g.fillArc(10,120,100,100, 90, -60); /*pocetak na vrh i ispod se crta drugi luk, ispunjen kruzni isecak na 60 stepeni udesno */
       g.fillArc(120,120,100,50, 270,-210); /*fragment neispunjene elipse; isto kao
        g.fillArc(120,120,100,50, 60, 210);*/

}

}

--------------------------------------------------------------------------------

Primer apleta koji crta niz ispunjenih, koncentricnih krugova, naizmenicno crvenih i zelenih.

import java.applet.*;
import java.awt.*;
 

public class Bullseye extends Applet {

  public void paint(Graphics g) {

    int rectLeft, rectTop, rectHeight, rectWidth;
    int appletHeight = this.getSize().height;
    int appletWidth = this.getSize().width;

    for (int i=8; i >= 0; i--) {
      if ((i % 2) == 0) g.setColor(Color.red);
      else g.setColor(Color.green);

      // Centriranje pravougaonika
      rectHeight = appletHeight*i/8;
      rectWidth = appletWidth*i/8;
      rectLeft = appletWidth/2 - i*appletWidth/16;
      rectTop = appletHeight/2 - i*appletHeight/16;
      g.fillOval(rectLeft, rectTop, rectWidth, rectHeight);
    }

  }

}

Klasa koja crta ovu sliku je velicine 681 byte. Ekvivalentna GIF slika je velika 1,850 byte, dakle do tri puta vise.
--------------------------------------------------------------------------------

Poligoni






U Javi su pravougaonici definisani pomocu pozicije svojeg gornjeg levog ugla, visine i sirine. Implicitno se podrazumeva da pravougaonik nije rotiran. Ako jeste, smatra se specijalnim slucajem poligona, tj. objekta iz klase java.awt.Polygon.

Poligoni su definisani svojim temenima bez dodatnih pretpostavki osim da leze u dvodimenzionalnoj ravnii.Osnovni konstruktor klase Polygon je
public Polygon(int[] xpoints,
               int[] ypoints,
               int npoints)
xpoints je niz koje sadrzi x koordinate temena poligona, a ypoints niz koje sadrzi y koordinate njegovih temena. Oba niza imajui duzinu npoints.

Primer konstrukcije pravouglog trougla:
int[] xpoints = {0, 3, 0};
int[] ypoints = {0, 0, 4};
Polygon pTrougao = new Polygon(xpoints, ypoints, 3);

Da bi obaj trougao bio iscrtan,  unutar paint() metode se poziva iz klase java.awt.Graphics metod drawPoligon() :

g.drawPolygon(myTriangle);

Dakle, sintaksa metoda je public void drawPolygon(Polygon p)

Postoji i druga verzija metode drawPolygon() koja ima signaturu:

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

a poziva se kao:

g.drawPolygon(xpoints, ypoints, xpoints.length);

Postoji  i polimorfna metoda fillPolygon().
Sintaksa metoda:

g.fillPolygon(myTriangle);
g.fillPolygon(xpoints, ypoints, xpoints.length());
--------------------------------------------------------------------------------

Visestruke linije (polylines)
Java automatski zatvara poligone koje nacrta.

Ako zelite iscrtati otvorene poligone, koristi se metod drawPolyline().
Sintaksa:
public abstract void drawPolyline(int[] xPoints,
                                  int[] yPoints,
                                  int nPoints)
 

  Zadaci za vežbanje

1. Napisati metod public void debljaLinija (int x, int y, int x1, int y1, int w, Graphics g) koji u ciklusu iscrtava deblje linije do w puta od osnovnih. Napisati aplet koji testira upotrebu ovog metoda.

2. Napisati metod public void bojaLinija (int x, int y, int x1, int y1, Color c, Graphics g) koji
iscrtava liniju u zadatoj boji. Podesavanje boje se odnosi samo na liniju koja se iscrtava, a po izlasku iz metoda, tekuca boja treba da ostane kao i pre ulaska u potprogram.
  Napisati aplet koji testira upotrebu ovog metoda.
  Napomena: dozvoljeno je koristiti metod g.GetColor() koji vraca vrednost tekuce boje.

3. Napisati aplet koji ce omoguciti da korismik slobodno izcrtava linije.
Napomena: dozvoljeno je koristiti metode fillRect, fillOval za iscrtavanje tacaka, kao i dodatno dugme koje ce brisati ekran (upotrebiti metod za uklanjanje pravougaonika clearRect).
 
 

                                                Kružni dijagrami (pie charts)
 

Napisati aplet koji iscrtava nekoliko kružnih isečaka u obliku kružnog dijagrama , gde boje i veličine lukova se zadaju u programu.

kruzni dijagram border=

import java.awt.*;
import java.applet.*;

public class KruzniDijagram extends Applet
{
    double [] vred=new double [6]; /*udeo vrednosti u dijagramu*/
    int [] kriske=new int [6]; /* stepen luka svake kriske*/
   Color [] boje=new Color[6]; /*boje svake kriske */

    public void init()
    { double ukupno=0;

     /* zadaju se neke vrednosti, ciji odnos mora prikazati kruzni dijagram */
      vred[0]=1000;  vred[1]=600;  vred[2]=650;  vred[3]=1300;  vred[4]=400;     vred[5]=1450;

  /* svaki element niza se prikazuje u velicini lukova od 0 do 360 => formiranje vrednosti lukova */
   for (int i=0; i<6; i++) ukupno+=vred[i];
   for (int i=0; i<6; i++) kriske[i]=(int) (vred[i]/ukupno*360);

  /* zadavanje boje kriski */
  boje[0]=Color.red;   boje[1]=Color.green;   boje[2]=Color.blue;   boje[3]=Color.gray;
  boje[4]=Color.red;     boje[5]=Color.yellow;
}

 public void paint(Graphics g)
 {
        int start=0;
       for (int i=0; i<6; i++)
         {     g.setColor(boje[i]);   /* boja tekuceg isecka */
               g.fillArc(20,20,200,200,start, kriske[i]); /* na start se doda kriske[i] i dobija se
                   pocetni ugao za sledeci isecak */
              start+=kriske[i];
        }
  }

}
 
 

U ovom primeru umesto zadavanja boja u formi RGB tripleta,

Color medGray = new Color(127, 127, 127);
Color cream = new Color(255, 231, 187);
Color lightGreen = new Color(0, 55, 0);
upotrebljene su predefinsane boje
Color.red, Color.blue,...
Boje su u Javi instance klase java.awt.Color. Obavezno je importovati tu klasu pre upotrebe boja.. 
 
Nekoliko najčešće korištenih boja dostupne su i po nazivu. To su:
Color.black
Color.blue
Color.cyan
Color.darkGray
Color.gray
Color.green
Color.lightGray
Color.magenta
Color.orange
Color.pink
Color.red
Color.white
Color.yellow
Boja nije svojstvo izvesnog stringa, elipse i slično, nego  deo objekta tipa Graphics koji obavlja crtanja. Za promenu boje potrebno je promijeniti boju objekta iz Graphics. I sva tekuća  iscrtavanja poprimaju tu boju, do sledeće izmene.
Kad se aplet počne izvršavati, njegova boja je crna. Može se promeniti stavljajući npr. g.setColor(Color.red). Može se vratit na početnu ako se pozove g.setColor(Color.black).

Digresija:
Sistemske boje
Počev od  Java 1.1, postoji klasa java.awt.SystemColor koja je podklasa od java.awt.Color i omogućuje korištenje boja za nativne komponente. Na primer, ako želite pozadinu apleta obojiti kao i pozadinu prozora, onda u  init() metodi se obavi podešavanje:
 
public void paint (Graphics g) {
 
  g.setColor(SystemColor.control);
  g.fillRect(0, 0, this.getSize().width, this.getSize().height);
 
}
 
Raspložive su sledeće sistemske boje:
SystemColor.desktop // Background color of desktop
SystemColor.activeCaption // Background color for captions
SystemColor.activeCaptionText // Text color for captions
SystemColor.activeCaptionBorder // Border color for caption text
SystemColor.inactiveCaption // Background color for inactive captions
SystemColor.inactiveCaptionText // Text color for inactive captions
SystemColor.inactiveCaptionBorder // Border color for inactive captions
SystemColor.window // Background for windows
SystemColor.windowBorder // Color of window border frame
SystemColor.windowText // Text color inside windows
SystemColor.menu // Background for menus
SystemColor.menuText // Text color for menus
SystemColor.text // background color for text
SystemColor.textText // text color for text
SystemColor.textHighlight // background color for highlighted text
SystemColor.textHighlightText // text color for highlighted text
SystemColor.control // Background color for controls
SystemColor.controlText // Text color for controls
SystemColor.controlLtHighlight // Light highlight color for controls
SystemColor.controlHighlight // Highlight color for controls
SystemColor.controlShadow // Shadow color for controls
SystemColor.controlDkShadow // Dark shadow color for controls
SystemColor.inactiveControlText // Text color for inactive controls
SystemColor.scrollbar // Background color for scrollbars
SystemColor.info // Background color for spot-help text
SystemColor.infoText // Text color for spot-help text
 

Domaći: Modifikovati program tako da boja i veličine lukova se uzimaju kao vrednosti elementa
param unutar apleta.

Učitavanje slika



Slike koje se prikazuju pomocu Java apleta ucitavaju se s mreze preko URL koji locira datoteku sa slikom. Mogu se nalaziti na serveru, lokalnom disku,... ili bilokoje odrediste do ko applet ima dozvoljen pristup preko URL. Npr. URL koji ukazuje na lokalni disk Vseg racunara ne mora biti pristupacan nekom s mreze, tako da aplet moze da Vam i ne radi korektno na mrezi, iako je funkcionisao na lokalnom racunaru.
Najcesce se slike stavljaju u isti direktorijum gde je i applet ili u onaj gde je i HTML datoteka. Obicno se slika postavi u appletov direktorijum ako se se  koristiti u svim instancama apleta, a u HTML direktorijum ako razlicite instance appleta koriste razlicite slike. Treca mogucnost je staviti sve slike u neki posebni direktorij i onda preko <PARAM> oznake zadati lokaciju apletu.
Ako je poznat tacan URL slike, moze se ucitati pomocu metode getImage():

URL imageURL = new URL("http://www.google.com/logo.gif");
java.awt.Image img = this.getImage(imageURL);

Ili u jednoj naredbi:

Image img = this.getImage(new URL("http://www.google.com/logo.gif"));

Metoda getImage() pripada klasi java.applet.Applet. Za URL objekte koristi se klasu java.net.URL. Nuzno je da u korisnickim programima budu te klase importovane ako se koriste.

              Metodi getCodeBase() i getDocumentBase()
 

Ako se ne zna tacan URL slike, ali se znate njeno ime i da se ona nalazi u istom direktoriju kao i applet, moze se koristiti varijanta metode getImage() koja uzima URL i ime datoteke. Koristite appletovu metodu getCodeBase() da dobijete URL appletovog direktorijuma:

Image img = this.getImage(this.getCodeBase(), "test.gif");

Metoda getCodeBase() vraca objekt tipa URL koji pokazuje na direktorijum iz kojeg je applet dosao.

Ali, ako je slika  u istom direktorijumu kao i HTML datoteka, moze se  koristiti isti metod getImage(), ali sa getDocumentBase(). Vratice se  URL koji pokazuje na direktorijum u kojem se nalazi HTML stranica koja je pozvala applet.
Image img = this.getImage(this.getDocumentBase(), "test.gif");

Ako se slika ucitava s Interneta, moze potrajati dok se ne ucita celokupna. Ali se ona moze  iscrtavati odmah nakon spajanja na neki od pomenutih URLova. Java se stara za update kako podaci budu stizali, bez Vase intervencije.
Sve slike koje applet koristi ucitavaju se  u metodi init(). Nije dobra praksa da se ucitavaju unutar metoda paint() jer ce se svaki put pri obnovi appleta, slike ucitavati iz pocetka!

    Skaliranje slika
 

Prikaz slike u pravoj veličini
Jednom kad je slika učitana, može se prikazati u metodi paint() pomoću metoda drawImage():

g.drawImage(img, x, y, io)

img je objekat klase Image koji je već učitan unutar metoda init().
x je apscisa, y ordinata gornjeg levog ugla slike.
io je objekat klase koja implementira interface ImageObserver.
Interface ImageObserver propisuje kako Java rukuje asinhronim obnavljanjem slike kad se ona učitava sa udaljenog računara. S obzirom da  klasa java.applet.Applet implementira ImageObserver dovoljno je upotrebiti ključnu reč this za odgovarajući argument metoda drawImage() čime se naznačuje da se želi ipotrebiti ImageObserver trenutno aktivnog appleta.
Dakle, Vi sami ne pozivate metode ImageObservera, ali evo sadržaj definicije interfejsa:

     public interface ImageObserver {
         public static final int ABORT
         public static int final ALLBITS
         public static final int ERROR
         public static int final FRAMEBITS
         public static final int HEIGHT
         public static int final PROPERTIES
         public static final int SOMEBITS
         public static int final WIDTH
        public boolean imageUpadte(Image slika, int int2flegovi, int x, int y, int width, int height)
}

Interface poseduje jednu metodu imageUpadte. Ona otkriva sta je poyvano. Interface ne morate sami implementirati, jer je to ucinjeno AWT klasom komponent i svim njenim podklasama.
 

     Digresija: Koncept interfejsa u Java-i
     Interfejsi su nacin da se u javi nadoknadi funkcionalnost izgubljena eliminisanjem visestrukog nasledjivanja. Interfejsi su slicni apstraktnim klasama u smislu da poput apstraktnih klasa definišu šablon za korišćenje izvedenih klasa. Ali, postoje i razlike, jer interfejsi, za razliku od klasa, nisu izvedeni od klase Object, ali i mnogo značajnije jedna klasa može da implementira (nasledi) više interfejsa.
   Interfejsu su korisni ako se želi označiti da če neke klase imati isto ponašanje, npr. proizvoditi iste zvučne efekte kao znak uspeha, crtati linije iste boje,...
  Dakle, interfejs predstavlja (slikovito rečeno) obećanje neke klase da će implementirati određeni skup funkcija definisan u interfejsu. Klase nasleđuju interfejs navođenjem kljušne reči implements:
  interface Kretanje {
     public void Kreni() {...}
     public void Stani() {...}
 }
  class Vozilo implements Kretanje {
     public void Kreni() {...}
     public void Stani() {...}
 }
   Interfejsi se mogu medjusobno nasledjivati, npr. interface Kretati extends Kretanje {...}
   Kada je interfejs definisan, moguce je kreirati objekt u koji ce se smestiti bilo koja klasa koja implementira dati interfejs:
  public Kretanje VratiInterfejs() {...}
  Kretanje k= VratiInterfejs();
  k.Kreni();
  k.Stani();
  Klasa moze naslediti neku klasu, i implementirati jedan ili vise interfejsa:
  class Prva extends Klasa implements PrviInterfejs {...}
  class Druga extends Klasa implements PrviInterfejs, DrugiInterfejs {...}
  Interfejs moze sadrzati i promenljive, preciznije konstante, jer sve "promenljive" u interfejsu implicitno dobijaju modifikator static kao prefiks i vidljive su iz svih klasa koje implementiraju dati interfejs.

Metoda paint() obavlja crtanja slike u pravoj veličini počevši od gornjeg levog ugla:
public void paint(Graphics g) {
  g.drawImage(img, 0, 0, this);
}

                                            Skaliranje slika

Slika se moze skalirati unutar zadatog pravougaonika koristeci  formu metode drawImage():

public boolean drawImage(Image img, int x, int y,
                         int width,  int height, ImageObserver io)

img je objekat klase Image koji je već učitan unutar metoda init().
x je apscisa, y ordinata gornjeg levog ugla slike.
width i height su dimenzije pravougaonika u koji se zeli smestiti slika.
io je objekat klase koja implementira interface ImageObserver.

Ako skaliranje nije u skladu s proporcijama slike, rezultat je  izobličen prikaz.
Izobličenje se može prevazići metodima getHeight() i getWidth() koje daju pravu veličinu slike, te se  ona može skalirati na odgovarajući način. Na primer, ako se želi smanjiti na polovinu:
g.drawImage(img, 0, 0, img.getWidth(this)/2, img.getHeight(this)/2, this);

Napisati aplet koji učitava sliku i uvećava je za zadati faktor:

import java.awt.*;
import java.applet.*;

public class Zum extends Applet {

  private Image slika;
  private int faktor;
 

/*Metoda init() čita dva parametra apleta od kojih jedan daje ime slike, a drugi faktor povećanja.*/
  public void init() {
    String datotekaNaziv  = this.getParameter("slikalokacija");
    this.slika       = this.getImage(this.getCodeBase(), datotekaNaziv);
    this.faktor = Integer.parseInt(this.getParameter("faktorskaliranja"));
  }

/* Metoda paint() računa dimenzije i zatim crta skaliranu sliku. */
  public void paint (Graphics g) {
    int sirina    = this.slika.getWidth(this);
    int duzina   = this.slika.getHeight(this);
    int skaliranaSirina  = sirina * this.faktor;
    int skaliranaDuzina = duzina * this.faktor;
    g.drawImage(this.slika, 0, 0, skaliranaSirina, skaliranaDuzina, this);
  }

}

<APPLET CODE="Zum.class" CODEBASE="http://www.matf.bg.ac.zu/~jelenagr/java/classes"
ARCHIVE="Zum.jar"
WIDTH=200 HEIGHT=200>

<param name="slikalokacija" value="slika.gif">

<param name="faktorskaliranja" value=2>

</APPLET>

Slika pre zumiranja

Slika nakon 2* zumiranja


 

Zašto je skaliranje vršeno u metodi paint(), a ne  u metodi init(), s obzirom da  veličina slike se ne menja dinamički?
Zato što tokom izvršavanja metode init() slika verovatno neće biti do kraja učitana, te metodi getWidth() i getHeight() će vratiti vrednost koja utiče da  skaliranje se neće obaviti.
Na primer:

import java.awt.*;
import java.applet.*;

public class Zum extends Applet {

  Image slika;
  int skaliranaSirina, skaliranaDuzina;
 
 

/*Metoda init() čita dva parametra apleta od kojih jedan daje ime slike, a drugi faktor povećanja.*/
  public void init() {
    String datotekaNaziv  = this.getParameter("slikalokacija");
    slika       = this.getImage(this.getDocumentBase(), datotekaNaziv);
   int faktor = Integer.valueOf(this.getParameter("faktorskaliranja")).intValue();
    int sirina    = slika.getWidth(this);
    int duzina   = slika.getHeight(this);
    skaliranaSirina  = sirina * this.faktor;
    skaliranaDuzina = duzina * this.faktor;

  }

/* Metoda paint() računa dimenzije i zatim crta skaliranu sliku. */
  public void paint (Graphics g) {
    g.drawImage(this.slika, 0, 0, skaliranaVisina, skaliranaDuzina, this);
  }

}