Informaticasite van het Lauwers College te Buitenpost                 © R.J. van der Beek
 

Hoofdstuk 18 Java

18.1 De basis, de methode paint

  18.1.1. Installatie

Er bestaan heel veel verschillende programmeertalen en technieken, en Java is daar één van. Het is een zogenaamde objectgeoriënteerde programmeertaal.
Java werd ontwikkeld in 1991 door Sun Microsystems. In die tijd werd voor de taal nog de naam Oak gebruikt. Oak werd tot Java omgedoopt in 1995.
Het is nu één van de meest gebruikte programmeertalen.
Java is ontworpen voor toepassingen voor het internet, meestal worden er programma's gemaakt die onderdeel van een webpagina vormen.
Zo'n programma dat in een browser kan draaien wordt een applet genoemd.
Je kunt eventueel ook zelfstandig draaiende programma's met Java maken.

Je hebt verschillende ontwikkelomgevingen (dat zijn programma's waarmee je Java-software kunt maken) voor Java, wij gaan JCreator gebruiken.
Je zou ook Netbeans kunnen gebruiken (downloaden door te klikken op Netbeans IDE)
of BlueJ (downloaden door te klikken op BlueJ IDE)

Maar als je JCreator wilt installeren moeten er eerst twee andere programma's voor Java worden geïnstalleerd:
  1. Om te kunnen werken met JCreator is het nodig dat de Java Development Kit (afgekort als JDK, soms ook SDK of J2SDK, dat is Java Sun Development Kit) geïnstalleerd is op het systeem.
    Als je een Java-programma schrijft (het bestand dat de code bevat heeft de extensie java) moet het eerst gecompileerd worden. Java-programma's worden niet gecompileerd tot direct uitvoebare bestanden, maar tot zogenaamde bytecode (zo'n bestand krijgt de extensie class). Die bytecode is machine-onafhankelijk, en JDK compileert java-code tot bytecode met de extensie class. JDK kun je downloaden door te klikken op j2sdk-1_3_1_11-windows-i586.exe downloaden
    Installeren gaat heel eenvoudig door op de naam van dat bestand te dubbelklikken.
    Je kunt de nieuwste versie downloaden via website van Sun: http://java.sun.com/j2se/downloads/index.html

    Kies je de eerste versie, dan wordt die standaard geïnstalleerd in C:\jdk1.3.1_11

  2. Je hebt ook nog de Java Run Environment (afgekort als JRE) nodig. Dat wordt ook wel de Java Virtuele Machine (JVM) genoemd.
    Als je een webpagina met een applet bekijkt dan zorgt JVM er voor dat de bytecode van de applet word gelezen en tot machinetaal wordt gecompileerd.

    Het zit er dik in dat JVM al op je computer staat, want dat programma zorgt er voor dat je browser de Java-applets kan laten zien.
    Als je de JDK (zie hiervoor) installeert dan wordt JRE trouwens ook tegelijk geïnstalleerd.
    Je kunt het eventueel ook apart installeren, dan moet je het eerst downloaden van de site www.java.com/getjava

  3. Als die twee programma's zijn geïnstalleerd dan kan JCreator worden geïnstalleerd.
    Je kunt het downloaden door te klikken op JCreator250.exe downloaden

    De nieuwste versie kun je downloaden via http://www.jcreator.com

    Je installeert het heel eenvoudig door op de naam van het bestand te dubbelklikken.
    Er worden nog wel een aantal vragen gesteld, maar je kunt overal het voorstel accepteren, klik dus steeds op Next.

  18.1.2. Compileren

Een computerprogramma wordt door een speciaal programma vertaald in machinetaal voor gebruik op een bepaalde computer. Afhankelijk van de omstandigheden heet zo'n vertaalprogramma een assembler, een compiler, of een interpreter.
  • Assembler
    Een assembler wordt gebruikt voor het vertalen van assembler-programma's naar machinecode.
    Omdat een Assembler-programma specifiek is voor een bepaalde processor, heb je voor verschillende computers verschillende programma's nodig, die elk door een overeenkomstige assembler worden vertaald. Elke assembler-opdracht wordt in een machinetaal-opdracht vertaald.
  • Compiler
    Het voordeel van alle programmeertalen, behalve assembler, is dat ze geschreven kunnen worden onafhankelijk van de computer. Er is dus maar één programma nodig, dat op een computer naar keuze kan worden vertaald naar de betreffende machinecode. Zo'n vertaalprogramma heet een compiler. De compiler zelf is wel machine-specifiek; die moet immers de machinecode van de betreffende computer kennen. Het door de programmeur geschreven programma (de source code, of kortweg source, of in het Nederlands: broncode) is echter machine-onafhankelijk.
    Vertalen met behulp van een compiler is gebruikelijk voor de meeste programmertalen, zoals Pascal, C en C++.
  • Interpreter
    Een directere manier om programma's te vertalen is met behulp van een interpreter. Dat is een programma dat een opdracht van de broncode leest, het vertaalt in machinetaal, en de opdrachten daarna direct uitvoert. De interpreter is net zo als een compiler specifiek voor de machine, maar de broncode is machine-onafhankelijk.
    Het woord interpreter betekent letterlijk tolk, een tolk vertaalt immers ook per regel en spreekt die regel dan direct uit.
    Het voordeel van een interpreter boven een compiler is dat er geen aparte vertaalslag nodig is, het vertalen gebeurt immers pas als het programma wordt uitgevoerd. Het nadeel is echter dat het uitvoeren van het programma langzamer gaat, en dat eventuele fouten in het programma niet in een vroeg stadium gemeld worden. De fouten worden immers pas ontdekt als de computer aan de opdracht toe is en probeert die te vertalen.
    Vertalen met behulp van een interpreter gebeurt bij sommige Basic-talen, en verder bij html en de daarin ingebedde taal Javascript.
  • Compiler+interpreter of compiler+compiler
    Bij Java is voor een gemengde aanpak gekozen. Java-programma's zijn bedoeld om via het Internet te verspreiden. Het verspreiden van de gecompileerde versie van het programma is echter niet handig want de machinecode is machine-specifiek.
    De aanpak die daarom voor Java wordt gehanteerd is een compiler die de broncode niet naar machinecode vertaalt, maar naar een nog machine-onafhankelijke tussenliggende taal, die bytecode wordt genoemd. Die eerste stap wordt door JDK uitgevoerd, en het bestand met de bytecode krijgt de extensie class.
    Die bytecode kan via het Internet worden verspreid, dus als je een applet op een website zet moet het html-bestand worden geupload, maar ook het bijbehorende class-bestand.
    Als je een website met daarop een applet bekijkt m.b.v. een browser, dan moet de computer het applet (dus het java-programma) uitvoeren. Bij de eerste browsers werd het op de computer van de gebruiker met behulp van een interpreter uitgevoerd. Tegenwoordig gebeurt ook de tweede stap met een compiler, die JIT-compiler wordt genoemd (JIT is de afkorting van Just In Time, het wordt vertaald op het moment dat het nodig is). De bytecode is dusdanig eenvoudig, dat die compiler erg simpel kan zijn en kan worden ingebouwd in Internet-browsers. Dat gebeurt door de JVM-pluging.
    JVM zorgt ook voor beveiliging; het controleert wat er precies gebeurt tijdens de uitvoering van het Java-programma, en lang niet alles wordt toegestaan. Die controle en de vertaling vergt wel wat tijd, daarom duurt het soms vrij lang voordat je het applet ziet verschijnen.

  18.1.3. Het eerste programma

  • Start JCreator op, klik in de menubalk op File → New.
    Klik op het tabblad Projects, dan zie je onderstaand venster.



  • Klik dan op Basic Java Applet
    Voer als naam van het project bijvoorbeeld Opdracht1 in.
    Zorg er voor dat de naam met een hoofdletter begint, en dat er geen spaties in de naam zitten!
    (Java maakt onderscheid tussen kleine letters en hoofdletters, dus opdracht1 en Opdracht1 zijn voor Java verschillende dingen, denk daar goed om!)
    En bij Location kun je aangeven waar het opgeslagen moet worden.
    Klik op de drie puntjes achter het venster voor de locatie, dan kun je door de mappen bladeren. Kies de map uit, waarin je het project op wilt slaan (Bijv. D:\java).
    Zet een vinkje voor Create new workspace en klik op OK.
    Omdat er een vinkje voor Create new workspace staat, wordt er een map aangemaakt met de naam Opdracht1 in de map die je had uitgekozen. Dus bijvoorbeeld D:\java\Opdracht1

  • Nadat je op OK hebt geklikt verschijnen in het linker gedeelte van het venster de namen van twee bestanden:
    • Opdracht1.htm
    • Opdracht1.java
    Dubbelklik op Opdracht1.java, dan verschijnt onderstaand venster.



  • In het rechter gedeelte staan al een aantal opdrachten, waarmee je een standaard-java programma begint.
    Voer het volgende in:

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

    public class Opdracht1 extends Applet 
    {
     // Declareer variabelen (dat mag ook in de methode paint)
        int r;
        String s;
        Font lett1;

         public void init()
         {
             this.setSize(200,200);
         }

         public void paint(Graphics g)
         {
      // Voorzie de variabelen van waarden
             r = 40;
             s = "LauwersCollege";
             lett1 = new Font("Arial",Font.BOLD,16);
      // vertel g welk lettertype je wilt gebruiken
             g.setFont(lett1);
      // druk tekst en vormen af
             g.drawString("Vormen en tekst",60,20);
             g.drawString(s,60,40);
             g.drawRect(60,50,100,100);
             g.fillRect(70,60,80,80);
             g.fillArc(10,70,r,r,0,360);
             g.drawLine(10,120,50,120);
         }
    }

  • Klik dan op het schijfje, dan wordt het bestand opgeslagen.

  • En klik dan in de menubalk op Build → Compile Project (je kunt ook op F7 drukken)
    Dan wordt het programma vertaald in bytecode, en er wordt eerst gecontroleerd op fouten.
    Er verschijnt onder in beeld, als alles goed gaat, Process completed. En dat betekent dat er geen fouten in zitten.

  • Klik tenslotte in de menubalk op Build → Execute Project (je kunt ook op F5 drukken)
    Dan krijgen we het resultaat te zien, er verschijnt een nieuw venster met de tekening, in de zogenaamde appletviewer. Zie hier onder:

  18.1.4. Uitleg van het eerste programma

Klasse
Een programma bestaat uit een pakket van alle daarin benodigde klassen.
Een klasse bestaat grotendeels uit een opsomming van de methoden die er deel van uitmaken. In het voorbeeld is dat er maar één namelijk paint.
Behalve methoden mogen er in een klasse ook variabelen worden gedeclareerd, dat wil zeggen namen (van plaatsen in het geheugen) met een waarde.


Klasse-header en -body
Elke definitie van een klasse bestaat uit een header (een kopregel) en een body. De header van de klasse Opdracht1 in het voorbeeldprogramma is:
public class Opdracht1 extends Applet
De body die daaronder volgt moet in zijn geheel tussen accolades { en } staan: daarmee wordt aangegeven welke methoden er allemaal bij deze klasse horen.

Het is gebruikelijk om deze accolades recht onder elkaar te zetten, op een aparte regel. Alle tekst die daartussen staat wordt een stukje ingesprongen. Zo kun je gemakkelijk zien waar de methode begint en eindigt.

public: bruikbaar voor de omgeving
In de header van de klasse-definitie staat in ieder geval het woord class, om aan te geven dat het een klasse-definitie betreft. Direct daarachter staat de door de programmeur gekozen naam, in dit geval Opdracht1. Nog voor het woord class staat vaak het woord public. Dat geeft aan dat de klasse van buitenaf gebruikt mag worden. Omdat het voorbeeldprogramma een applet is, moet deze klasse inderdaad public gemaakt worden, omdat de klasse door de browser gebruikt wordt. Eventuele andere klassen, die alleen binnen het programma gebruikt worden, hoeven niet public te zijn.

extends: voortbouwen op eerder werk
Achter de naam van de klasse mag in de header het woord extends staan, gevolgd door de naam van een andere, al bestaande klasse. Daarmee kunnen we aangeven dat deze klasse niet van de grond af aan wordt opgebouwd, maar een uitbreiding is van de bestaande klasse. Omdat we een applet willen maken zorgen we er voor dat de klasse een uitbreiding is van de bestaande klasse Applet. Daardoor hoeven we alleen nog maar aan te geven in hoeverre ons programma afwijkt van een blanco-applet.

Methode: opsomming van opdrachten.
In de methoden zijn de eigenlijke opdrachten ondergebracht.
Elke definitie van een methode bestaat uit een header (een kopregel) en een body. De header van de methode paint in het voorbeeldprogramma is:
public void paint(Graphics g) 
De body die daaronder volgt moet in zijn geheel tussen accolades { en } staan.

void: doet dingen, maar berekent niets
De eigenlijke header van de methode begint met het type van de methode. Sommige methoden kunnen een waarde berekenen, en dan geeft het type aan wat voor soort waarde dat is. Maar er zijn ook methoden die er alleen maar voor dienen om een aantal opdrachten uit te voeren; de methode in het voorbeeld is er zo een. In dat geval moet als type het woord void worden gebruikt. Letterlijk betekent dit leeg, en dat klopt, want de resultaatwaarde van deze methode is leeg.

De methoden init en paint
Het derde woord in de methode-header is de naam van de methode. De naam van de methode mag in principe door de programmeur bedacht worden. Maar de browser begint altijd de opdrachten uit te voeren die in de methode init staan, en daarna die van paint.
In de methode init worden vaak de beginwaarden van de variabelen gezet, en er kan worden bepaald hoe het tekenvel er uit moet zien.
M.b.v. de opdracht this.setSize(200,200); wordt de grootte van het applet vastgelegd.
this slaat dus op het applet, en dat mag ook worden weggelaten.
Je kunt in de methode init bijvoorbeeld ook de achtergrondkleur van het applet vastleggen (zie volgende paragraaf)
Na de methode init gaat de browser de opdrachten in de methode paint uitvoeren. Daarin staan de tekenopdrachten, dus wil je iets zien dan moet er wel een methode paint zijn.

Parameters van de methode
Achter de naam van de methode volgt een opsomming van de zogenaamde parameters van de methode. Die staan tussen ronde haakjes en dus geen accolades. Zelfs als er geen parameters zijn moeten de haakjes er staan, met niets er tussen.

Object waarop de methode werkt
Eén van de opdrachten in de methode paint is: g.drawString("Vormen en kleuren",60,20);
Elke methode die wordt aangeroepen neemt een bepaald object onder handen. In de methodeaanroep wordt dat object als eerste genoemd, voor de punt. Daarom wordt het ook objectgeoriëenteerd programmeren genoemd.
In het voorbeeld is dat het object g.
Een Graphics-object kun je het beste beschouwen als een teken-apparaat. Dus g is een object dat op verzoek teksten (en andere dingen) kan tekenen.

Achter de naam van het object volgt een punt, en daarna de naam van de methode die we willen aanroepen. In het voorbeeld willen we dat het object g een tekst voor ons gaat afdrukken, en daarom roepen we de methode drawString aan.

Bij de aanroep van de methode drawString moeten we nog drie parameters meegeven: welke tekst er afgedrukt moet worden, en op welke plaats dat moet gebeuren: hoeveel pixels van de linkerrand en hoeveel van de bovenrand.

Importeren van klassen
In het voorbeeldprogramma worden twee klassen gebruikt uit een bibliotheek van Javastandaardklassen:
  • Applet, omdat onze klasse Opdracht1 daar een uitbreiding van is
  • Graphics, omdat dat het objecttype is van de parameter van paint
Om deze klassen te mogen gebruiken, moeten we aan het begin van het programma aangeven dat deze klassen worden geïmporteerd. Dit gebeurt met een speciale import-aanwijzing aan het begin van het programma:
import java.awt.*;
import java.applet.*;

De klassen in de Java-bibliotheek zijn georganiseerd in zogenaamde packages.
De klasse Applet zit in package java.applet (waarin naast Applet zelf nog een paar klassen zitten die iets met applets te maken hebben).

In ons voorbeeld hoeven we uit dit package alleen de klasse Applet te gebruiken.
De klasse Graphics zit in package java.awt. Ook de klasse Font zit in dat package.
Daarm hadden we in plaats van
import java.awt.*;
import java.applet.*;

import java.applet.*;
ook de volgende import-regels kunnen gebruiken:
import java.awt.Graphics;
import java.awt.Font;
import java.applet.Applet;

Dat scheelt geheugenruimte.

Awt is de afkorting van Abstract Window Toolkit. Deze toolkit heet abstract omdat de klassen niet specifiek bedoeld zijn voor een bepaald operating system. Je kunt er dus window-gebaseerde programma's mee maken die op meerdere computersystemen werken.
Er zijn veel meer packages.
  • Het package java.lang wordt als enige automatisch geïmporteerd, dat hoef je niet apart te vermelden. Deze klassenbibliotheek wordt altijd gebruikt, hij bevat de basis-bouwstenen.
  • java.io bevat alle klassen voor in- en uitvoer
  • java.net bevat alle klassen voor programmering van het netwerk
  • java.util bevat een reeks klassen met allerlei praktische hulpmiddelen
Commentaar
Voor de lezer van een programma is het heel nuttig als er wat toelichting bij het programma staat geschreven. Dit zogenaamde commentaar wordt door de compiler geheel genegeerd, maar zorgt ervoor dat het programma beter te begrijpen is. Er zijn in Java twee manieren om commentaar in een programma te zetten:
  • alles tussen de tekencombinatie /* en de eerstvolgende teken-combinatie */ (mogelijk pas een paar regels verderop)
  • alles tussen de tekencombinatie // en het einde van de regel
Tijdens het testen van het programma kunnen de commentaar-tekens ook gebruikt worden om één of meerdere opdrachten tijdelijk uit te schakelen.

Regel-indeling
Er zijn geen voorschriften voor de verdeling van de tekst van een Java-programma over de regels.
Het is gebruikelijk om elke opdracht op een aparte regel te schrijven, maar er mogen meerdere opdrachten op één regel worden geschreven. Soms komt dat de overzichtelijkheid van het programma ten goede.
Bij hele lange opdrachten is het meestal beter om de tekst over meerdere regels te verspreiden.
Verder is het een goed gebruik om af en toe een regel over te slaan: tussen verschillende methoden, en tussen groepjes opdrachten die bij elkaar horen.
Voor de plaatsing van spaties zijn er weinig voorschriften. Maar gereserveeerde woorden mogen niet aan elkaar vast worden geschreven: public void paint mag niet worden geschreven als publicvoidpaint.
Verder worden regels van methoden enz. meestal ingesprongen (vier posities is gebruikelijk) ten opzichte van de accolades die de body begrenzen.

Combineren van declaratie en toekenning
Variabelen moeten worden gedeclareerd, en krijgen op een gegeven moment een waarde. Een variabele moet worden gedeclareerd voordat je hem gebruikt, dat hoeft niet beslist in de kop van het programma.
Je kunt de declaratie van een variabele met de eerste toekenning aan die variabele ook combineren. In plaats van
int r;
r = 60;

mag je ook schrijven:
int r = 60;

Dit kan alleen bij de eerste toekenning aan de variabele, want je kunt een variabele maar één keer declareren.

new
Variabelen krijgen op een gegeven moment een waarde. Bij de meeste typen moet je dan het woordje new toevoegen, behalve bij getallen en strings. Bijvoorbeeld:
Font lett1
lett1 = new Font("Arial",Font.BOLD,16);

of gecombineerd:
Font lett1 = new Font("Arial",Font.BOLD,16);

  18.1.5. Color, Dimension, if-opdracht

De klasse Color
Als je in een bepaalde kleur wilt laten tekenen dan moet je de methode setColor gebruiken, en daarbij moet je een kleur als parameter meegeven.
Zo'n kleur is in Java een object op zichzelf.
Er is een bibliotheek-klasse Color, waarin een aantal methoden staan maar ook een aantal Color-objecten.
Deze constanten kun je pakken door de naam van de klasse en de naam van de constante te noemen, gescheiden door een punt, bijvoorbeeld: Color.blue
Hier staat er voor de punt niet de naam van een object (zoals bij methode-aanroepen), maar de naam van de klasse.
Het aldus verkregen Color-object kunnen we gebruiken als parameter bij de aanroep van de methode setColor:
g.setColor(Color.blue);

In de klasse Color zijn de volgende Color-constanten beschikbaar:
black, red, green, blue, white, yellow, orange, pink, cyan, magenta, gray, light_gray, dark_gray

Je kunt ook RGB-kleuren gebruiken. Dat kan bijvoorbeeld op de volgende manier:
Color k = new Color(100, 200, 30);
g.setColor(k);


Als de klasse Color in een programma wordt gebruikt, moet deze aan het begin van het programma worden geïmporteerd. Net als de klasse Graphics zit de klasse Color in het package java.awt.

De klasse Dimension
Je hebt in de vorige paragraaf gezien dat de afmetingen van het applet m.b.v. setSize kan worden vastgelegd. Maar meestal worden de afmetingen niet in het java-programma, maar in de html-code vastgelegd.
Dat kan er bijvoorbeeld zo uitzien:
<applet code = Opdracht1.class   width = 300 height = 200> </applet>

Maar je kunt dan binnen het applet toch wel vaststellen hoe groot het venster is, dan moet je gebruik maken van de klasse Dimension.
Je moet dan eerst een object van dat type declareren, bijvoorbeeld zo: Dimension d;
En dan kun je de afmetingen van het venster op de volgende manier in dat object laten stoppen:
Dimension d = this.getSize();
Dat object bevat dan de breedte en de hoogte, en die kun je dan op de volgende manier opvragen: int breedte = d.width;
int hoogte = d.height;


Voorwaardelijke opdracht
Als je de grootste cirkel wilt laten tekenen, die in het venster past, dan moet je eerst de straal bepalen.
De straal is de helft van de breedte, of de helft van de hoogte. Dat hangt ervan af welke van de twee het grootst is.
Dat kun je op de volgende manier programmeren:
if (breedte > hoogte)
   { straal = hoogte / 2; }
else
   { straal = breedte / 2; }


Ten slotte volgt hier het volledige programma:

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

public class Oefening2 extends Applet  
{ 
 // Declareer de te gebruiken lettertypen en kleuren
     Color kleur1; 
     Color kleur2; 

     public void init()  
     { 
 
  // Specificeer nu de kleuren
          kleur1 = Color.red; 
          kleur2 = new Color(60,60,122); 
  // geef aan wat de achtergrondkleur van het applet is 
      setBackground(kleur2); 
     } 

     public void paint(Graphics g)  
     { 

      Dimension d; 
      d = this.getSize(); 
      int breedte = d.width; int hoogte = d.height; 
      int straal = hoogte/2; 
      if (breedte<hoogte) {straal=breedte/2;} else {straal=hoogte/2;} 
      int x=breedte/2-straal; int y=hoogte/2-straal; 
      g.setColor (kleur1); 
      g.fillOval (x, y, 2*straal, 2*straal); 
      straal = straal - 10; 
      g.setColor (Color.green); 
      g.fillOval (x+10, y+10, 2*straal, 2*straal); 
      straal = straal - 10; 
      g.setColor (Color.blue); 
      g.fillOval (x+20, y+20, 2*straal, 2*straal); 
     } 
}

Je ziet dan de volgende tekening:



En het grappige is dat als je de grootte van het venster verandert de tekening ook meteen wordt aangepast.
De methode paint wordt niet alleen bij de start van het applet uitgevoerd, maar ook elke keer als er iets aan het venster verandert. Dus als het venster groter of kleiner wordt gemaakt, of als er wordt gescrolld.

Opgaven.
Maak nu opgave 1 van hoofdstuk 18 (Java)