13. Tekenen in een applet (2)

In hoofdstuk 2 van deze cursus zijn we al een aantal figuren tegengekomen die we met Java kunnen tekenen:

   Lijnstuk:    Rechthoek:

   Ellips:

   Cirkel:

Als we een cirkel willen tekenen, moeten h en b natuurlijk gelijk zijn. In het voorbeeld noemen we die d (diameter).

We hebben gezien dat we rechthoeken en ellipsen kunnen opvullen door fill te gebruiken in plaats van draw, dus zo:

    g.fillRect (x, y, b, h);
    g.fillOval (x, y, b, h);

   

Tekenen in kleur

Wi je met rood gaan tekenen, dan kun je die kleur krijgen met:

      g.setColor (Color.red);

   

De klasse Color bevat 13 voorgedefinieerde kleuren, namelijk:

 

Color.black

 Color.green

Color.pink

 

Color.blue

 Color.lightGray

Color.red

 

Color.cyan

 Color.magenta

Color.white

 

Color.darkGray

 Color.orange

Color.yellow

 

Color.gray

 

 

   

Zo kunnen we bijvoorbeeld de volgende gekleurde figuren maken:

   

Verder kun je de hoeken van een rechthoek afronden met de functies drawRoundRect en fillRoundRect. Zoals hieronder is te zien, komen er twee argumenten bij voor de mate van ronding.

   

Figuren met 'diepte'

Java kan ook rechthoeken tekenen waarvan de randen relief suggereren. Daarvoor bestaat de methode fill3DRect. Deze methode heeft een vijfde argument van het type boolean, waarmee we kunnen kiezen voor een donkere rechthoek met een lichte rand of andersom.

Beide varianten zie je hieronder. Ter vergelijking is er rechts een 'normale' rechthoek bij gezet.


   

Zelf kleuren definiëren

Kleuren kun je ook zelf definiëren. Dat kan als volgt:

       int rood=60, groen=10, blauw=25;
       Color kleur = new Color (rood, groen, blauw);
       g.setColor (kleur);
       g.drawString ("Is dit paars?", 10, 100);

De variabelen rood, groen en blauw moeten waarden hebben van 0 tot en met 255.

We kunnen een applet maken met drie tekstvakken om waarden voor rood, groen en blauw in te voeren. Om te voorkomen dat we van alles in drievoud moeten intypen, zullen we diverse objecten als arrays van drie elementen (0-2) uitvoeren.

// Zelf kleuren mengen met drie getallen (RGB)
import java.applet.*;
import java.awt.*;
public class Kleuren extends Applet {
   boolean fout;
   // rgb[0] t/m rgb[2]: om de getalswaarden
   // van rood, groen en blauw te bevatten.
   int rgb[ ] = new int[3];
   TextField vak[ ] = new TextField[3];
   // De labels tekst[0] t/m tekst[2] geven de 3
   // namen van de kleuren bij de invoervakken.
   Label tekst[ ] = new Label[3];
   String kleuren[ ] = {"rood:", "groen:", "blauw:"};
   Button knop = new Button ("toon");

   public void init () {
      setBackground (Color.lightGray);
      for (int i=0; i<3; i++) {
         vak[i] = new TextField("0");
         tekst[i] = new Label(kleuren[i]);
         add (tekst[i]);
         add (vak[i]);
      }
      add (knop);
   }

   public void paint (Graphics g) {
      // We tekenen eerst een donkere rechthoek,
      // die een schaduw moet suggereren.
      g.setColor (Color.darkGray);
      g.fillRect (15,15,400,240);
      g.drawRect (0,0,385,225);
      g.setColor (Color.white);
      g.fillRect (0,0,385,225);
      g.setColor (Color.black);
      if (fout)
         g.drawString ("Alleen 0-255!", 100, 100);
      else {
         Color kleur=new Color (rgb[0],rgb[1],rgb[2]);
         g.setColor (kleur);
         g.fillRect (100,50,200,130);
      }
   }

   int totByte (String s) {
      // levert -1 af als string s niet tot
      // int van 0-255 te converteren is.
      int lengte = s.length();
      s = s.trim();
      if (lengte > 3)
         return -1;
      for (int i=0; i<lengte; i++) {
         char k = s.charAt(i);
         if (k<'0' || k>'9')
            return -1;
      }
      int getal = Integer.parseInt(s);
      if (getal > 255)
         return -1;
      else
         return getal;
   }

   public boolean action (Event e, Object o) {
      if (e.target==knop) {
         fout = false;
         for (int i=0; i<3; i++) {
            String temp = vak[i].getText();
            rgb[i] = totByte(temp);
            if (rgb[i]==-1)
               fout = true;
         }
      }
      repaint();
      return true;
   }
}

De zelfgemaakte methode totByte zet de string (die in het tekstvak is ingetypt) om in een getal. Als dit geen getal van 0-255 oplevert, wordt -1 afgegeven.

En zo ziet de applet eruit:

    

Onregelmatige figuren 

In Java kun je ook figuren maken die met ellipsen, rechthoeken en dergelijke moeilijk te tekenen zijn.

Stel dat we een pijl willen tekenen, zoals hier afgebeeld:

Om deze figuur te tekenen, zouden we 12 punten met elkaar moeten verbinden.

We kunnen gebruik maken van de methode drawPolygon. Deze vereist drie argumenten; een array van x-coördinaten en een van y-coördinaten. Het derde argument is de lengte van de arrays (die natuurlijk even groot zijn).

De methode paint om deze pijl te tekenen ziet er zo uit:

public void paint (Graphics g) {
   // array h voor de horizontale verplaatsing:
   int h[ ] = {10,70,70,170,190,
         220,190,220,190,170,70,70,10};
   // array v voor de verticale verplaatsing:
   int v[ ] = {60,10,40,40,20,20,
          60,100,100,80,80,110,60};
   g.drawPolygon (h, v, h.length);
}

Naast de methode drawPolygon is er ook fillPoygon, die natuurlijk dit soort figuren oplevert:

    

Argumenten meegeven aan een applet

Je kunt aan een applet argumenten meegeven vanuit het HTML-bestand, als je dat wilt.

De meeste figuren op deze pagina zijn getekend door de applet FiguurDemo.class, die telkens een ander argument meekrijgt.

In het HTML-bestand ziet dat er bijvoorbeeld voor de gele rechthoek zo uit:

<applet code = FiguurDemo.class
width = 320  height = 240>
param name = "figuur" value = "5">
</applet>

Bij param name moet je de naam opgeven waaronder het meegegeven argument binnen de applet kan worden binnengehaald. Let erop dat je als argument alleen strings kunt meegeven, in dit geval de string "5".

Binnen de applet wordt (meestal in de methode init) de string binnengehaald. In de applet FiguurDemo.java gebeurt dat aldus:

       String tmp = getParameter ("figuur");

Hierna bevat de String tmp de waarde "5" (of een andere waarde die in het html-bestand aan "figuur" is meegegeven).

Als we deze string in een getal willen omzetten, zou dat bijvoorbeeld zo kunnen:

       int figuur = Integer.parseInt(tmp);

Laten we eens een wat groter programma bekijken waarin het meegeven van argumenten wordt gebruikt.

We gaan de achtergrondkleur, de letterkleur en de lettergrootte als argumenten meegeven. Ons HTML-bestand ziet er zo uit:

<applet code=ParamDemo.class
width=320 height=240>
<PARAM NAME=letterkleur VALUE="yellow">
<PARAM NAME=achtergrkleur VALUE="blue">
<PARAM NAME=lettergrootte VALUE="32">
</applet>

In de applet worden al deze waarden binnengehaald. Om te voorkomen dat de applet stukloopt als verkeerde argumenten worden meegegeven, heb ik wat foutcontroles ingebouwd.


// Demo van parameters die worden
// doorgegeven uit het HTML-file.
import java.applet.*;
import java.awt.*;
public class ParamDemo extends Applet {
   String letterkleur;

   public void init () {
      letterkleur = getParameter("letterkleur");
      String achtergrkleur = getParameter("achtergrkleur");
      if (achtergrkleur != null) {
         if (achtergrkleur.equals("blue"))
            setBackground (Color.blue);
         else if (achtergrkleur.equals("green"))
            setBackground (Color.green);
         else setBackground (Color.lightGray);
      }
   }

   public void paint (Graphics g) {
      if (letterkleur != null) {
         if (letterkleur.equals("yellow"))
            g.setColor (Color.yellow);
         else if (letterkleur.equals("orange"))
            g.setColor (Color.orange);
         else g.setColor (Color.black);
      }
      int letgr = 15;
      try {
       letgr=Integer.parseInt(getParameter("lettergrootte"));
      }
      catch (java.lang.NumberFormatException e) { }
      g.setFont(new Font ("Helvetica", Font.BOLD, letgr));
      g.drawString ("ParameterDemo", 20, 100);
   }
}

De twee gebruikte foutcontroles zijn:

  • Het gebruik van een string waar geen waarde aan toegekend is geeft problemen. In Java heet dat het object null. Bij de twee kleuren-strings controleren we of er wel een waarde is binnengekomen. Anders is de waarde namelijk gelijk aan null. Let erop dat dit iets anders is dan een lege string. Die ziet er namelijk uit als "" en kan probleemloos gebruikt worden.
  • Een string kun je omzetten naar int met de functie parseInt uit de klasse Integer. Deze methode controleert niet of de string wel een geldig heel getal bevat. Vandaar dat we eventuele fouten opvangen met een try-catch-constructie. Tussen de accolades achter catch hoeven we niets te schrijven omdat we de lettergrootte al op 15 hebben gezet. Komt er geen nieuwe waarde binnen, dan blijft de waarde gewoon 15.

    

Opdracht 13.1

Schrijf een applet met twee tekstvakken en een knop. Na invoeren van de lengte en de breedte en klikken op de knop wordt een rechthoek met de gewenste lengte en breedte getekend.

Opdracht 13.2

Dezelfde applet als 13.1. Zorg dat de applet een melding geeft als de ingevoerde strings geen positieve hele getallen kunnen zijn of als de getallen te groot zijn om in het appletvenster te passen (ongeacht de grootte die in het html-bestand is meegegeven.

Opdracht 13.3

Laat een rechthoek tekenen waarvan lengte, breedte en opvulkleur bepaald worden door argumenten uit het html-bestand. Zorg dat de applet meldingen geeft als de meegegeven argumenten onjuist zijn. Ook moet vermeld worden als de meegegeven lengte en/of breedte negatief of te groot zijn om in het appletvenster te passen.

(c) 2003-2008, Thomas J.H.Luif