Objectgeoriënteerd programmeren met JavaFX

Objectgeoriënteerd programmeren met JavaFX

A Inleiding

Vooraf

De module “Objectgeoriënteerd programmeren met JavaFX” is een vervolg op de module “Visueel programmeren met JavaFX”.
In die module heb je kennis gemaakt met de basisvaardigheden van programmeren, zoals:

  • voor een probleem een bijpassend algoritme bedenken;
  • de verschillende basisstructuren voor het beschrijven van een algoritme: de opeenvolging, de herhaling en de keuze gebruiken;
  • de verschillende typen variabelen herkennen en gebruiken;
  • het verschil tussen primitieve typen en referentietypen herkennen;
  • de regels bij conversie toepassen;
  • een aantal methoden uit Java gebruiken.

In de module "Objectgeoriënteerd programmeren met JavaFX" gaan we verder in op het paradigma van objectgeoriënteerd programmeren.
Zoals je hebt geleerd, werkt Java met een bibliotheek van bestanden die klassen worden genoemd.
Een programmeur kan in zijn eigen programma gebruik maken van voorgeprogrammeerde klassen.
In deze module leer je hoe je naast gebruik te maken van voorgeprogrammeerde klassen ook zelf klassen kunt schrijven.
Daarnaast gaan we ook in op een complexe datastructuur: de array.

Maar voordat we daarmee aan de slag gaan, krijg je in de video op de volgende pagina een overzicht van datgene dat je geleerd hebt in de module “Visueel programmeren met JavaFX”.
Vervolgens zijn er een drietal opdrachten waarmee je je programmeervaardigheid kunt opfrissen.

★ Aan de slag 1

Bekijk de video “Terugblik visueel programmeren met JavaFX”.


★ Aan de slag 2

Schrijf een app die een Syracuserij maakt van een getal.
Een Syracuserij is een rij getallen die begint met een positief, geheel getal.
Het volgende getal in de rij krijg je door het getal door twee te delen, als het getal even is.
Is het een oneven getal, dan wordt het getal met 3 vermenigvuldigd en vervolgens wordt bij het resultaat 1 opgeteld.

In de afbeelding zie je de Syracuserij van het getal 23.
Bij 1 stopt de rij omdat daarna steeds de reeks 4 2 1 herhaald wordt.

★ Aan de slag 3

Schrijf een app die een virtuele dobbelsteen gooit, die alleen de getallen 1 tot en met 4 kan gooien.
Wanneer je op de dobbelknop klikt dan wordt de dobbelsteen geworpen en het resultaat in het dobbelveld geplaatst.
Tevens wordt het aantal keren bijgehouden dat er 1, 2, 3 of 4 is gegooid.
Wanneer je op de 1000x-knop klikt, dan wordt 1000 keer de dobbelsteen geworpen en wordt bijgehouden hoeveel keer er 1, 2, 3 en 4 is gegooid.

★ Aan de slag 4

Schrijf een app die uit een woord de klinkers (de letters e, a, o, i, u) haalt.
De gebruiker moet eerst een woord intypen.
De app loopt het woord letter voor letter langs en controleert of een letter een klinker is.
Als het geen klinker is dan moet de letter meegenomen worden naar het nieuwe woord.

Leerdoelen

Na verwerking van deze module:

  • kun je uitleggen wat een object, een klasse en een instantie zijn;
  • kun je uitleggen wat attributen, methodes en events zijn;
  • weet je wat de API is;
  • kun je een eenvoudige klasse programmeren;
  • weet je wat de functie van de constructor is;
  • kun je een klasse toepassen in een app;
  • weet je wat data-hiding inhoudt;
  • weet je waarvoor de import-opdracht gebruikt wordt;
  • kun je uitleggen hoe overerving werkt;
  • weet je wat overriding betekent;
  • weet je de functie van de klassen Canvas en GraphicsContext;
  • kun je een figuur tekenen met behulp van de methodes uit de klasse GraphicsContext;
  • kun je een klasse programmeren die een tekening maakt;
  • weet je wanneer je een array gebruikt;
  • kun je een array maken en vullen;
  • kun je enkele zoekalgoritmen uitleggen;
  • kun arrays toepassen in een app;
  • kun je arrays van objecten toepassen;
  • weet je een aantal sorteeralgoritmen;
  • kun je de sorteeralgoritmen bubbe sort, selection sort, insertion sort en quicksort uitleggen;
  • weet je hoe een recursief algoritme werkt;
  • weet je welke algoritmen efficiënter zijn dan anderen in een gegeven situatie;
  • kun je verschillende sorteeralgoritmen toepassen in een app.

Bijlagen

Bij deze module horen de volgende bijlagen:

Zo werkt het

Je bent begonnen in de module Objectgeoriënteerd programmeren met JavaFX.
Deze module bestaat uit meerdere onderdelen.
In ieder onderdeel vind je, verdeeld over verschillende pagina's, informatie in de vorm van teksten, afbeeldingen en video's.

Daarnaast ga je zelf aan de slag. Onder het kopje "Aan de slag" vind je steeds toepassingsopdrachten.
Deze opdrachten maak je alleen of met een klasgenoot.

Er zijn ook toetsen. Deze herken je aan de blauwe knop met daarop "Adaptieve Toets".
Een toets bestaat uit meerdere vragen.
Dat kunnen gesloten vragen zijn, die door de computer worden nagekeken, of open vragen, die moet je zelf nakijken.
Bij een enkele vraag moet je een bestand uploaden.

Van de toetsen wordt, als je ingelogd bent, de voortgang bijgehouden.
Het resultaat vind je onder de knop "Voortgang".
Deze voortgang is ook door je docent te bekijken.

Succes met de module Programmeren met JavaFX.

B Objectgeoriënteerd

Inleiding

Moderne software is complex en het ontwikkelen ervan is een tijdrovende bezigheid.
Niet voor niets worden releases van nieuwe software vaak maanden uitgesteld om de laatste fouten eruit te halen.
Het schrijven van dergelijke computerprogramma’s wordt niet door één programmeur in een paar dagen gedaan, maar is het werk van een team programmeurs die daar soms een paar jaar mee bezig zijn.
De taken moeten verdeeld worden en daarom is het wenselijk het programma in min of meer los van elkaar te ontwikkelen delen te kunnen schrijven.

Ook kan er gebruik gemaakt worden van bouwstenen, zodat de programmeur niet ieder programmaonderdeel van de grond af hoeft te ontwikkelen.
Om bijvoorbeeld een knop te programmeren kan hij een bouwsteen voor een standaardknop gebruiken.
Die hoeft dan alleen maar aangepast te worden om de specifieke taak binnen het programma uit te voeren.

Uit het bovenstaande volgt dat het belangrijk is, dat een computerprogramma een duidelijke structuur heeft.
Daarom zijn er in de loop van de tijd verschillende methoden bedacht om een computerprogramma te structureren.
Je spreekt in dit verband van een programmeerparadigma.
In deze module ga je in op het paradigma, waarop Java is gebaseerd: het objectgeoriënteerde paradigma.

★ Aan de slag 5

In de tekst wordt gesproken over programmeerparadigma’s.

  1. Zoek op het internet de betekenis van het woord paradigma op.
  2. Leg in je eigen woorden uit wat je onder een programmeerparadigma verstaat.

Objecten

Bekijk de video over het gebruik van objecten bij het programmeren.

 

★ Aan de slag 6

  1. Noem drie attributen van het object invoerVeld uit de klasse TextField.
  2. Noem drie methoden van het object invoerVeld uit de klasse TextField.

Klassen

In de video heb je gezien dat een auto eigenschappen (attributen) heeft, acties kan uitvoeren (methoden) en gebeurtenissen kan ondergaan (events) die kenmerkend zijn voor een auto.

Een auto is van een model van een bepaald merk, heeft een kleur en rijdt op een bepaalde brandstof.
Dat geldt voor iedere auto. Ook kan iedere auto Starten, Rijden, Parkeren en Stoppen.
Wanneer je een bepaalde auto, een object auto, wilt beschrijven, dat zal hij moeten voldoen aan die algemene beschrijving, het model.
De beschrijving van een model is de klasse. Om de auto van de buurman te beschrijven maak je gebruik van de klasse Auto, waarin alle attributen, methoden en events zijn vastgelegd.

De auto van de buurman die gemaakt wordt op grond van de klasse Auto heet een instantie van Auto.

★ Aan de slag 7

  1. Maak de volgende opgaven.
    1. Wat is het verschil tussen een klasse en een object?
    2. Wat is een instantie?
  2. Een klassendefinitie kan niet alle denkbare eigenschappen en bewerkingen vastleggen.
    Waarom niet?

Klassen - 2

Wanneer je een programma schrijft in Java dan beschrijf je de verschillende klassen die in het programma nodig zijn.
Een klasse is in feite een verzameling objecten.
Daarbij heeft een klasse een naam, een aantal eigenschappen (in Java: attributen), een aantal acties (in Java: methoden) en een aantal gebeurtenissen (in Java: events).
Gelukkig hoef je niet alle klassen zelf te schrijven, want er is een bibliotheek van standaard klassen: de API (Application Programming Interface).
De API is onderverdeeld in packages.
Ieder package bevat een aantal bij elkaar horende klassen.
Wij zullen met name gebruik maken van de packages javafx.scene.control en java.lang.
Wanneer alle benodigde klassen gereed zijn, is de programmacode klaar.
Er moet een methode zijn met een gereserveerde naam, die als eerste wordt aangeroepen, wanneer een programma wordt opgestart. Dat is de methode main().
Alle andere methoden worden uiteindelijk vanuit deze startmethode aangeroepen.

★ Aan de slag 8

  1. Welke klassen, die we al eerder gebruikt hebben, zitten in het package javafx.scene.control?
  2. Wat is de functie van de methode main()?

Klasse Dobbelsteen

Om ervaring op te doen met het ontwerpen en schrijven van een klasse ga je een eenvoudig dobbelspel programmeren.
In dit spel mag een speler drie keer gooien met maximaal drie dobbelstenen.
Hij kan besluiten om een of meerdere stenen te laten liggen.
Het doel van het spel is om na drie worpen een zo hoog mogelijke score te behalen.
De interface van het spel staat hiernaast afgebeeld.


De objecten
Welke objecten zijn er te onderscheiden in dit spel?
Wanneer je naar de interface kijkt, zie je twee knoppen: Start Spel en Dobbel.
Deze twee objecten zijn instanties van de klasse Button.
Er zijn drie velden die het resultaat van de worp laten zien en een vierde veld dat de totale score weergeeft.
Dit zijn instanties van de klasse NumberField.
Tenslotte zijn er nog drie selectievakjes. Door een selectievakje aan te vinken geeft de speler aan dat hij deze dobbelsteen laat liggen.
Deze objecten zijn instanties van de klasse Checkbox.

Behalve de objecten die je op de interface ziet, zijn er nog drie objecten: de dobbelstenen waarmee gegooid moet worden.
Java kent geen standaardklasse Dobbelsteen. Die moet je zelf ontwerpen.

Definitie van een klasse
In Java is de basisvorm van een klassendefinitie:
toegang class Naam { body }

Het woord class is in Java een gereserveerd woord en duidt het begin van de definitie van een klasse aan. Daarachter staat de naam van de klasse.
Het is in Java gebruikelijk om de naam van een klasse altijd met een hoofdletter te beginnen.
Voor de class staat een woord dat de toegang tot de klasse specificeert.
Wij komen hier later in deze paragraaf op terug.
Tussen toegang en class staan vaak woorden als static, abstract of final.
Deze woorden geven de klasse een speciale betekenis, die we hier verder niet zullen bespreken.
Ook tussen de naam en de linkeraccolade kunnen nog extra aanduidingen voorkomen.
In de body staan de definities van de attributen, de constructor en de methoden.
De attributen bevatten de eigenschappen van de objecten in de klasse. De methoden definiëren de acties.
De constructor is een speciale methode, die de naam van de klasse zelf heeft.
In de constructor is vastgelegd, wat er moet gebeuren bij de constructie van een nieuwe instantie van de klasse.

★ Aan de slag 9

De basisvorm van een klassendefinitie is: toegang class Naam { body }
Wat staat er in de body van een klassendefinitie?

★ Aan de slag 10

Implementatie van de klasse
Een implementatie van de klasse Dobbelsteen zou er als volgt uit kunnen zien:

public class Dobbelsteen {

  //velden

  private int worp;

  //constructor

  public Dobbelsteen() {

  }

  //methoden

  public void dobbel() {
     double randomGetal = Math.random();
     worp = (int)(6*randomGetal)+1;
  }

  public int getWorp() {
     return worp;
  }
}

 

  1. Om een klasse te schrijven in JavaEditor klik je in het menu op Bestand ->   Nieuw -> Java.
  2. Typ de implementatie van de klasse Dobbelsteen in.
  3. Sla de klasse op onder de naam Dobbelsteen in een aparte map WerpSpelProject.

Klasse Dobbelsteen - 2

Als eerste wordt in de klasse vastgelegd welke gegevens beheerd zullen worden.
De klasse Dobbelsteen bevat één attribuut, worp van het type int.

Het volgende onderdeel van de klassendefinitie is een constructor.
De constructor zorgt voor het construeren van een object en de initialisatie van de velden.
In onze klasse Dobbelsteen is de constructor leeg.
In dat geval krijgen alle velden een standaard beginwaarde.
Voor numerieke velden is dat de waarde 0.
Een lege constructor mag weggelaten worden.
In het vervolg zullen wij dat doen.

Stel dat je instanties van Dobbelsteen zou willen creëren die een verschillend aantal ogen hebben dan zou het begin van de klasse als volgt gedefinieerd kunnen worden:

public class Dobbelsteen {
  //velden
  private int worp;
  private int aantalZijden;
  //constructor
  public Dobbelsteen (int zijden) {
     aantalZijden = zijden;
  }

★ Aan de slag 11

  1. Wat is de functie van de constructor?
  2. In de tekst wordt een voorbeeld gegeven van een constructor, die het mogelijk maakt om instanties van Dobbelsteen te creëren met een verschillend aantal zijden.
    Alleen de constructor aanpassen en een veld aantalZijden toevoegen is niet voldoende.
    Wat moet er in de methoden aangepast worden om de nieuwe klasse Dobbelsteen goed te laten werken?

★ Aan de slag 12

In de methode dobbel() staan twee statements.

In het statement double randomGetal = Math.random(); staat een aanroep van de methode random() uit de klasse Math.
Met deze methode kun je willekeurige getallen laten berekenen.
Dergelijke getallen worden toevalsgetallen of random getallen genoemd.
Elke keer als je de methode random() aanroept, levert dat een willekeurig reëel getal tussen 0.0 en 1.0 op (0.0 en 1.0 komen zelf niet voor).

In het statement worp = (int)(6*randomGetal)+1; staat een expressie waarvan het resultaat een getal uit de verzameling {1, 2, 3, 4, 5, 6} is.
Het resultaat van de expressie is van het type double.
De variabele worp, waarin het resultaat wordt opgeslagen, is van het type int.

In dit geval moet de programmeur in de programmacode aangeven dat er een conversie van double naar int moet plaatsvinden.
Dat kan door het woord int tussen haakjes voor de expressie te zetten.
We noemen dit een expliciete conversie of casting.

Statische methode
Misschien is het je opgevallen dat de methode random() gebruikt wordt zonder dat er een instantie bestaat van de klasse Math.
In plaats van een objectnaam wordt in de aanroep van de methode de naam van de klasse zelf genoemd.

Een dergelijke methode heet een statische methode (static).

 

  1. Waarom mag Java deze conversie niet zonder meer uitvoeren?
  2. Bekijk het volgende voorbeeld:
    int x = 5;
    int y = 5;
    double r = x + y;


    In dit voorbeeld is er sprake van een conversie van int naar double.
    Voert Java deze conversie zonder meer uit?
  3. Leg je antwoord uit.
  4. Bekijk het volgende voorbeeld:
    double r = 18 / 5;
    Welke waarde wordt opgeslagen in de variabele r?
  5. Leg je antwoord uit.

Klasse Dobbelsteen - 3

Het grootste deel van de klassendefinitie bestaat uit methoden.
De basisvorm van een methodedefinitie is

toegang resultaattype
methodenaam(parameters) { statements }

In de klasse Dobbelsteen staan twee methoden:
dobbel(), die de dobbelsteen gooit en getWorp(), die het resultaat van de worp oplevert.

Als eerste wordt de toegang tot de methode geregeld.
Java kent vier niveaus van toegang: public, private, package en protected.
Wanneer de toegang private is dan kan een methode alleen binnen de klasse aangeroepen kan worden.

Voor een veld geldt in dat geval dat de waarde alleen binnen de klasse zelf direct kan worden opgevraagd of gewijzigd.
Bij een objectgeoriënteerd programma is het goed gebruik de velden te verbergen voor de buitenwereld.
Dit wordt data-hiding genoemd. Het verkleint de kans op oneigenlijk gebruik van de velden.
Wanneer een methode public is, is de methode volledig toegankelijk: vanuit de eigen klasse en ook vanuit andere klassen.

Als in de definitie de toegang ontbreekt, is automatisch de default-toegang van kracht.
De default-toegang is package, dat wil zeggen dat alle klassen binnen dezelfde package toegang hebben.
De protected-toegang wordt gebruikt bij overerving.
We komen daar later op terug.

Voor de naam van de methode dobbel() staat als resultaattype het woord void.
Het Engelse woord void betekent leeg. Dat wil zeggen dat deze methode geen resultaat heeft.
Het is een methode die wel een effect heeft, namelijk het wijzigen van het veld worp.

Package
Een package in Java bevat een aantal klassen die bij elkaar horen.
Een package kan bijvoorbeeld de onderdelen van een programma bevatten die te maken hebben met de GUI.

Om een package of een klasse uit een package te gebruiken in een program­ma,
maak je gebruik van de opdracht import, bv import javafx.scene.control.*

Bij het schrijven van een app maken wij gebruik van de packages javafx.application. javafx.stage, javafx.scene en javafx.event

 

★ Aan de slag 13

  1. Wat is het verschil tussen een private-methode en een public-methode?
  2. Waarom zullen private-methoden niet zo vaak voorkomen?

Klasse Dobbelsteen - 4

Het resultaattype van de methode getWorp() is int.
Deze methode levert een resultaat op: het aantal ogen van de worp.
Wanneer een methode een waarde moet teruggeven dan moet in de body van de methode staan welke waarde dat moet zijn.
Daartoe dient het return-statement:

    return expressie;

De expressie kan een getal, een variabele, een berekening of een aanroep van een methode of een combinatie hiervan zijn.
Het resultaat van de expressie moet van het juiste type zijn, zoals gespecificeerd in de declaratie van de methode: het resultaattype.
Verder zorgt het return-statement ervoor dat de uitvoering van de methode wordt beëindigd.
Dat betekent dat opdrachten, die na het return-statement in de body van een methode staan, nooit uitgevoerd worden.

Beide methoden hebben geen parameter.
Een voorbeeld van een methode met een parameter is de uitgebreide constructor van de klasse Dobbelsteen:

    public Dobbelsteen(int zijden) {
        aantalZijden = zijden;
      }


De parameter heeft een naam: zijden. De naam wordt voorafgegaan door de naam van een type of klasse: int.

★ Aan de slag 14

De header van een methode heeft de volgende vorm:
public boolean voegtoe(String naam)

  1. Van welk type is het resultaat van deze methode?
  2. Welke opdracht moet in ieder geval in de body van deze methode staan?
  3. Stel dat in een app een object adreslijst bestaat, dat een instantie is van de klasse waartoe de methode voegtoe() behoort.
    Je wilt de naam Turing toevoegen aan de adreslijst met behulp van deze methode.
    Wat is het juiste statement?
    1. adreslijst.voegtoe(“Turing”);
    2. Turing.voegtoe(adreslijst);
    3. boolean ok = adreslijst.voegtoe(“Turing”);
    4. boolean ok = Turing.voegtoe(adreslijst);

★ Aan de slag 15

  1. De header van een methode heeft de volgende vorm:
    public void gooi(int aantalStenen)
  2. Welk resultaat levert deze methode?
  3. Stel dat in een app een object spel bestaat, dat een instantie is van de klasse waartoe deze methode behoort.
    Je wilt met twee stenen gooien.
    Wat is het juiste statement?
    1. spel.gooi(2);
    2. 2.gooi(spel);
    3. int resultaat = spel.gooi(2);
    4. int resultaat = 2.gooi(spel);

Nu de klasse Dobbelsteen klaar is, kan begonnen worden met het programmeren van de WerpSpelApp.

★ Aan de slag 16

Nu de klasse Dobbelsteen klaar is, kan begonnen worden met het programmeren van de WerpSpelApp.

  1. Open een nieuwe FX-application en sla de app op onder de naam WerpSpelApp in de map WerpSpelProject (In die map moet ook de klasse Dobbelsteen staan).
  2. Ontwerp de interface zoals hieronder is aangegeven.
    Denk aan een correcte naamgeving voor de objecten.

Het gebruik

Het gebruik van de klasse Dobbelsteen in een app

In de app wordt er met drie dobbelstenen geworpen.
In het programma zullen dus drie instanties van de klasse Dobbelsteen moeten worden aangemaakt.
De eerste stap is de declaratie van drie velden: dobbelsteen1, dobbelsteen2 en dobbelsteen3.

   Dobbelsteen dobbelsteen1;
   Dobbelsteen dobbelsteen2;
   Dobbelsteen dobbelsteen3;

De declaratie creëert op zich nog geen object, maar geeft alleen maar aan dat er in de code een variabele met die naam mag voorkomen, die waarden kan krijgen van het aangegeven type.
De tweede stap is het creëren van een instantie van de klasse Dobbelsteen.
Dit gebeurt met de operatie new :

new naam(parameters);

Op de plaats van parameters kunnen 0, 1 of meer parameters staan, gescheiden door komma’s.
Het aantal en het type van de parameters moet overeenkomen met de definitie van een constructor van de betreffende klasse:

  dobbelsteen1 = new Dobbelsteen();
  dobbelsteen2 = new Dobbelsteen();
  dobbelsteen3 = new Dobbelsteen();

De declaratie en de creatie van de instanties van de klasse Dobbelsteen kan in een verkorte notatie onder de header van de app gezet worden:
public class WerpSpelApp extends Application {
  private Dobbelsteen dobbelsteen1 = new Dobbelsteen();
  private Dobbelsteen dobbelsteen2 = new Dobbelsteen();
  private Dobbelsteen dobbelsteen3 = new Dobbelsteen();

★ Aan de slag 17

  1. Zorg dat in de WerpSpelApp drie instanties van de klasse Dobbelsteen worden gecreëerd.
  2. Maak de volgende opgaven
    1. Schrijf de event-handler voor de startSpelKnop.
      Deze knop zorgt voor de initialisatie van het spel.
    2. Schrijf de event-handler voor de dobbelKnop.
      Denk daarbij aan het volgende:
      • In een spel mag maar drie keer geworpen worden.
      • Een steen die aangevinkt is, wordt niet geworpen.
      • Sla het applet op.

Fruitautomaat

De FruitautomaatApp simuleert de werking van een gokkast, ook wel fruitautomaat of eenarmige bandiet genaamd.
De speler start met 20 credits.
Wanneer de speler op de Speelknop klikt, wordt het aantal credits met één verlaagd.
Je verdient 2 credits wanneer je twee dezelfde symbolen (getallen) naast elkaar hebt staan.
Wanneer je drie dezelfde symbolen hebt, verdien je 5 credits en wanneer alle vier symbolen gelijk zijn krijg je 10 credits.
Je kunt een rol een speelronde vastzetten door de Holdknop in te drukken.
Door middel van de Collectknop kun je de prijs toevoegen aan het totaal aantal credits.

Naast de app zijn er twee andere klassen geschreven: een klasse Rol die de werking van de draaiende rol symbolen simuleert en een klasse Prijs die bepaalt of er een prijs uitgekeerd wordt en hoeveel credits de prijs bedraagt.

De klasse Rol kent de volgende methoden:
public int draai()
Deze methode geeft een getal van het type int (het symbool) dat gedraaid wordt.
public String getRol()
Deze methode geeft als resultaat een String die bestaat uit drie getallen onder elkaar.
Het middelste getal is het gedraaide getal.

public boolean getStatus()
Deze methode geeft aan of de rol mag draaien (true) of niet (false).
public void setStatus(boolean s)
Deze methode wijzigt de status van de rol in wel draaien (true) of niet draaien (false).

Een deel van de klasse kun je hier vinden.

★ Aan de slag 18

  1. De methode public int draai() genereert een willekeurig getal groter of gelijk 0 en kleiner of gelijk aan aantalSymbolen.
    Schrijf de body van de methode.

De methode public String getRol() is al geschreven.
Bestudeer de code van de methode en beantwoord daarna de volgende vragen.

  1. In de code wordt een lus gebruikt:
    (int i = draaigetal-1; i <= draaigetal+1; i++)
    Waarom gaat de lus van draaigetal-1 tot en met draaigetal+1?
  2. In de code staat ook een keuze:
    if (i < 0)
    Waarvoor is die keuze nodig?
  3. Wat doet de string \n in de code?
  4. Schrijf de body van de methode public boolean getStatus().
  5. Schrijf de body van de methode public void setStatus(boolean s).

Fruitautomaat - 2

De tweede klasse Prijs kent maar een methode:
public int bepaalPrijs(int rij1, int rij2, int rij3, int rij4)

Wanneer alle vier de rollen hetzelfde getal geven dan verdient men 10 credits.
Bij drie rollen die hetzelfde zijn, krijgt men 5 credits.
Bij twee dezelfde rollen naast elkaar worden 2 credits uitgekeerd.
In alle andere gevallen krijgt men niets.
Het raamwerk van de klasse staat hieronder:

  public class Prijs {

  //velden

  //constructor
  public Prijs() {

  }

  //methoden
  public int bepaalPrijs(int rij1, int rij2, int rij3, int rij4) {

  }
}

★ Aan de slag 19

  1. Schrijf de body van de methode bepaalPrijs().
  2. Tenslotte moet met behulp van de klassen Rol en Prijs de FruitautomaatApp geschreven worden.
    1. Ontwerp de interface van de app.
      Op het scherm staan vier instanties van de klasse TextArea: de objecten waarin de rollen getoond worden, twee instanties van de klasse Label, twee instanties van de klasse NumberField en zes instanties van de klasse Button.
      Denk aan een logische keuze van de namen voor de objecten.
    2. Creëer vier instanties van de klasse Rol, de vier rollen die gedraaid worden en een instantie van de klasse Prijs.
    3. Schrijf de event-handlers voor de zes knoppen.

C De klasse Application

Inleiding

Tot nu toe heb je bij het maken van apps dankbaar gebruik gemaakt van het werk dat JavaEditor voor je verricht. Het wordt tijd om de code die deze programmeeromgeving voor je genereert eens aan een nadere inspectie te onderwerpen.
Je bekijkt daarbij een eenvoudige app, dat een dobbelsteen simuleert.
In de app wordt gebruik gemaakt van de klasse Dobbelsteen.

★ Aan de slag 20

Op deze pagina vind je de code van de DobbelApp.
Alle tekst die staat tussen /* en */ is commentaar bij de code.
Hetzelfde geldt voor de regels die beginnen met //.
Lees de code door en beantwoord de volgende vragen:

  1. Wat gebeurt er in de regel
    private Dobbelsteen dsteen = new Dobbelsteen();?
  2. Schrijf de regel op waarmee de dobbelKnop wordt gecreëerd.
  3. Wat gebeurt er in de regel
    dobbelKnop.setFont(new Font("Dialog", Font.BOLD, 12));?
  4. Wat gebeurt er in de regel
    resVeld.setPrefHeight(49);?

★ Aan de slag 21

  1. Maak een nieuwe app en sla de app op onder de naam DobbelApp in een nieuwe map DobbelProject.
    (In die map moet ook de klasse Dobbelsteen staan.)
  2. Ontwerp de interface zoals is aangegeven.
    Denk aan een correcte naamgeving voor de objecten.
  3. Zorg dat er een instantie van de klasse Dobbelsteen wordt gecreëerd.
  4. Schrijf de event-handler voor de dobbelKnop.
  5. Sla de app op.

 

Import

Aan het begin van het applet staan de import-opdrachten:

    import javafx.application.Application;
    import javafx.scene.Scene;

    import javafx.scene.layout.Pane;
    import javafx.stage.Stage;
    import javafx.scene.control.*;
    import je.NumberField;
    import javafx.event.*;
    import javafx.scene.text.*;
    import javafx.scene.text.Font;
    import javafx.geometry.*;

Een import-statement geeft aan dat het programma één of meer klassen wil gebruiken, bijvoorbeeld import javafx.scene.control.Button;

Klassen zijn gegroepeerd in packages.
In het voorbeeld wordt de klasse Button uit het package javafx.scene.control geïmporteerd.
Andere voorbeelden zijn de klasse Scene die geïmporteerd wordt uit het package javafx.scene en de klasse Pane uit het package javafx.scene.layout:

    import javafx.scene.Scene;
    import javafx.scene.layout.Pane;


Als de app alle klassen uit een bepaald package wil importeren, kan dit aangegeven worden met een * (asterisk):

    import javafx.scene.control.*;
    import javafx.event.*;


Hier worden alle klassen uit de packages javafx.scene.control en javafx.event geïmporteerd.
De package java.lang hoeft als enige niet geïmporteerd te worden.
De klassen uit die package mogen altijd gebruikt worden.

★ Aan de slag 22

Welke klassen uit de package javafx.scene.control worden gebruikt in deze app?
Tip: Je kunt dit uitproberen door de verschillende klassen apart in de import-sectie te zetten.
Zie ook: Overview

Methode start

Na de importopdrachten volgt de header van de klassendefinitie:

    public class DobbelApp extends Application

Achter de naam van de klasse staat de toevoeging extends Application.
Dit betekent dat deze klasse een uitbreiding is van een andere klasse:
de klasse Application.
Daarmee erft DobbelApp de velden en methoden van de klasse Application.

In de code worden vervolgens alle instance variabelen gedeclareerd en de verschillende objecten gecreëerd:

  // Begin variabelen
  private Dobbelsteen dsteen = new Dobbelsteen=();
  private TextField resVeld = new TextField();
  private Button dobbelKnop = new Button();
  // Einde variabelen


Een instance variabele wordt buiten de methodes aan het begin van de klasse gedeclareerd.

De klasse DobbelApp heeft een aantal methoden. De methode start()zorgt voor de initialisatie van de app.
Deze methode wordt bij het opstarten van het programma standaard aangeroepen.

In de eerste regel van de methode start() wordt een object root van de klasse Pane gecreëerd:

    Pane root = new Pane();

Een Pane-object wordt gebruikt als een container, een lege doos, waarin de elementen van de gebruikersinterface opgeslagen worden, zoals een knop en een veld.

In de volgende regel wordt een Scene-object met de naam scene gecreëerd:

    Scene scene = new Scene(root, 198, 193);

Een scene bevat in JavaFX de inhoud van het venster.
Het venster zelf wordt de stage genoemd.
Het Scene-object heeft drie argumenten: root, 198 en 193.
Het eerste argument, root, is het zojuist gecreëerde Pane-object dat wordt doorgegeven (bekend gemaakt) aan het object scene.
Met de andere twee argumenten (198 en 193) worden de afmetingen in pixels van scene vastgelegd.

In het vervolg van de methode start() worden methoden aangeroepen, die de eigenschappen (hoogte, breedte, positie in het venster, lettertype etc.) van de objecten wijzigen.

★ Aan de slag 23

  1. Welke eigenschappen van de dobbelKnop worden gewijzigd in de methode start()?
  2. Welke eigenschappen van het resVeld worden gewijzigd in de methode start()?

 

Methode start - 2

De methode add() plaatst het object in de container, zodat het op het venster geplaatst kan worden:

    root.getChildren().add(resVeld);

Om de dobbelsteen te werpen in de DobbelApp moet de gebruiker op de knop klikken.
Het klikken op de knop heet een event (gebeurtenis) of action (actie).
Als een event plaatsvindt, moet het programma actie ondernemen: event-handling.

De methode setOnAction() vertelt aan de dobbelKnop wat er moet gebeuren als er op de knop geklikt wordt:

dobbelKnop.setOnAction(
         (event) -> {dobbelKnop_Action(event);}
  );

Het argument van setOnAction() heet een lambdafunctie:

(event) -> {dobbelKnop_Action(event);}

Met behulp van een lambdafunctie kan het afhandelen van een event gecodeerd worden, in dit geval het aanroepen van de methode dobbelKnop_Action(event), waarin de code staat die moet worden uitgevoerd als er op de knop geklikt wordt.

De laatste opdrachten hebben betrekking op het object primaryStage, dat een instantie is van de klasse Stage.
We hebben al eerder gelezen dat dat het venster is waarbinnen de scene zich afspeelt.

    primaryStage.setOnCloseRequest(e -> System.exit(0));
    primaryStage.setTitle("DobbelApp");
    primaryStage.setScene(scene);
    primaryStage.show();

Deze methoden zorgen achtereenvolgens voor het:

  • sluiten van het venster;
  • plaatsen van de naam in de titelbalk van het venster;
  • aangeven welke scene moet worden getoond;
  • tonen van de scene op het scherm.

De laatste methode is de event-handler van dobbelKnop: dobblelKnop_Action.
In deze methode staan de statements, die moeten worden uitgevoerd als de gebruiker van de app “iets met de knop doet”.

★ Aan de slag 24

  1. Wat is de functie van de methode root.getChildren().add()?
  2. Wat is de functie van de methode dobbelKnop.setOnAction()?
  3. Wat is de functie van de methode primaryStage.show()?

Overerving

Naast de methode start() bevat de DobbelApp nog een methode: main().
Elk Java-programma moet een methode main() bevatten.
Bij het uitvoeren van de app begint Java altijd met de opdrachten die in main() staan.

In dit geval staat er maar één opdracht: launch(args);

Deze opdracht zorgt ervoor dat de methode start() als eerste wordt uitgevoerd, waarbij een Stage-object wordt gecreëerd met de naam primaryStage.

Als je nauwkeurig de code bekijkt, zie je dat de methode niet voorafgegaan wordt door een punt en een klasse- of objectnaam.
Dat betekent, dat de methode uit de eigen klasse, de klasse DobbelApp afkomstig is.

In de programmacode van de klasse DobbelApp staat nergens een definitie van de methode launch().
Toch kent DobbelApp de methode wel.
Dit komt door een belangrijk kenmerk van objectoriëntatie, namelijk overerving (inheritance).
Een klasse kan worden gedefinieerd als een uitbreiding van bestaande klassen. Meestal gebeurt dat ook.
De nieuwe klasse, die op die manier ontworpen wordt, erft alle attributen (eigenschappen) en methoden en kan er nieuwe aan toevoegen of bestaande vervangen.

In dit voorbeeld is DobbelApp een uitbreiding van de bestaande klasse Application.
DobbelApp erft de velden en methoden van de klasse Application, waaronder de methode launch().

Aan deze klasse zijn een methode (dobbelKnop_Action) en objecten (dsteen, dobbelLnop etc.) toegevoegd.

De klasse Application kent al een methode start().
Deze methode wordt vervangen door de methode start() van DobbelApp.
Dit wordt overriding genoemd.
Met name bij het ontwerpen van grote programma’s is inheritance van belang.

★ Aan de slag 25

  1. Leg uit wat overerving (inheritance) inhoudt.
  2. Leg uit wat overriding inhoudt.

★ Aan de slag 26

Men noemt hergebruik wel het belangrijkste voordeel van overerving.
Wat zou daarmee worden bedoeld?

★ Aan de slag 27

  1. Welke stappen moeten er gedaan worden om een instantie van de klasse Button toe te voegen aan een app?
  2. Pas de programmacode van de DobbelApp aan, zodat bij het opstarten van de app het cijfer 1 in het resVeld staat.
  3. Pas de programmacode van de DobbelApp aan, zodat er een label met de tekst Dobbelsteen verschijnt boven het resVeld.
    Je mag hierbij geen gebruik maken van de menubalk en de object-inspecteur van JavaEditor.

Verdiepen

In een klasse kunnen twee of meer methoden met dezelfde naam voorkomen.
Dit heet overloading.
In de klasse Dobbelsteen zorgt de methode dobbel() ervoor dat er een getal uit de reeks {1, 2, 3, 4, 5, 6} gegenereerd wordt:

public void dobbel() {
     double randomGetal = Math.random();
     worp = (int)(6*randomGetal)+1;
}


Stel dat je nog een andere methode dobbel() wil schrijven, die een getal genereert uit een reeks, te beginnen bij 1, die je bij de aanroep van de methode opgeeft:

public void dobbel(int aantalOgen) {

}


Je hebt nu twee methoden met dezelfde naam, waarbij de eerste geen argument heeft en de tweede wel.
Wanneer de methode dobbel() wordt aangeroepen, bepaalt Java aan de hand van het argument welke versie wordt gebruikt.

★ Aan de slag 28

  1. Breid de klasse Dobbelsteen uit met de tweede methode dobbel().
  2. Test de methode.

Verdiepen - 2

Je hebt gezien dat een methode bijna altijd op een object werkt, maar soms op de klasse zelf.
Voorbeelden daarvan zijn de methode parseInt(), die werkt op de klasse Integer en de methode random(), die op de klasse Math werkt.
Een dergelijke methode heet een statische methode.
Een statische methode heeft in de header het gereserveerde woord static staan.
In het voorbeeld hiernaast is er een klasse Rekenen geschreven met een statische methode rondAf(), die een getal van het type double afrondt op twee cijfers achter de komma.

public class Rekenen {
  public static double rondAf(double dg) {
    dg = dg * 100 + 0.5;
    return (int) dg / (double) 100;
  }
}

★ Aan de slag 29

  1. Waarom wordt dg met 100 vermenigvuldigd?
  2. Waarom wordt daar 0.5 bij opgeteld?
  3. Waarvoor dienen de castings in de regel:
    return (int) dg / (double) 100;
  4. Schrijf de klasse Rekenen.
  5. Maak een app die als invoer vraagt om een reëel getal en dat afrondt op twee cijfers achter de komma.

D Tekenen

Methoden om te tekenen

Om te tekenen in JavaFX maken we gebruik van het package javafx.scene.canvas.
Dit package bevat twee klassen:

  • Canvas
  • GraphicsContext

Een canvas is een bitmapafbeelding, te vergelijken met een leeg vel papier waarop getekend kan worden.
Aan een canvas is een is een grafische context gekoppeld, die gebruikt wordt om tekenopdracht naar het canvas te sturen.
Voor de grafische context wordt een object van de klasse GraphicsContext gecreëerd, dat meestal de naam gc krijgt.

★ Aan de slag 30

Als voorbeeld maken we een app, die een horizontale lijn op het scherm tekent zoals hiernaast:

  1. Maak een nieuwe app en sla de app op onder de naam TekenLijnApp in een nieuwe map TekenLijnProject.
  2. Om gebruik te maken van het package javafx.scene.canvas moet het package geïmporteerd worden:
    import javafx.scene.canvas.*;  
  3. De volgende stap is het creëren van twee objecten:
  • een object van de klasse Canvas.
  • een object van de klasse GraphicsContext.

      // Begin variabelen
        Canvas canvas = new Canvas(400, 200);
        GraphicsContext gc = canvas.getGraphicsContext2D();
      // Einde variabelen


De argumenten van de constructor van de klasse Canvas bepalen de breedte en hoogte van het canvas.
NB. Het is logische om de maten van de scene gelijk te houden met de maten van het canvas.
Scene scene = new Scene(root, 400, 200);

  1. Door middel van de aanroep van de methode add() in de methode start() wordt het object in de container gezet, zodat het op het venster getoond wordt:
    root.getChildren().add(canvas);
  2. De volgende stap is het schrijven van een methode die de lijn tekent:
    public void tekenLijn()  {
           gc.strokeLine(50,50,250,50);
    }

De methode strokeLine() heeft 4 argumenten: de eerste twee geven de x- en y-coördinaten (in pixels) van het begin van de lijn, de laatste twee van het eind van de lijn.

Met de methoden strokeRect(x,y,b,h) en strokeOval(x,y,b,h) kun je respectievelijk een rechthoek (en vierkant) of een ellips (en cirkel) tekenen.
De eerste twee argumenten van deze methoden geven de plaats van de linkerbovenhoek van de figuur aan.
Een ellips of cirkel heeft geen linkerbovenhoek, maar je kunt daar wel een rechthoek omheen denken (de bounding box).
De laatste twee argumenten geven respectievelijk de breedte en de hoogte van de figuur.

De methoden fillRect() en fillOval() tekenen gevulde figuren.

  1. Om de lijn bij het opstarten van de app te laten tekenen zetten we de aanroep van de methode tekenLijn() in de methode start().

★ Aan de slag 31

  1. Waarom moet het package javafx.scene.canvas geïmporteerd worden?
  2. Welke argumenten heeft de methode strokeRect()?
  3. Maak een app die een rechthoek tekent.
  4. Maak een app die een cirkel tekent.

Om een tekst op het scherm te zetten kan gebruik gemaakt worden van de methode strokeText(string,x,y).
In het voorbeeld hebben we methode om een figuur te tekenen in de start()-methode gezet.
Je kunt de methode aanroep ook in de event-handler van een knop plaatsen.

  1. Maak een app die de tekst “JavaFX is fun” op het scherm tekent als je op de Java-knop klikt.

Kleuren

Om de kleur van een lijn te wijzigen maak je gebruik van de methode setStroke().
Wanneer je de vulkleur wilt aanpassen kan dat met de methode setFill().
Als argument geef je een variabele van de klasse Color mee.
Om deze klasse te kunnen gebruiken moet je de klasse importeren in het programma:

    import javafx.scene.paint.Color;

Er zijn in JavaFX 15 basiskleuren beschikbaar:

BLACK, BLUE, CYAN (of AQUA), GRAY, GREEN, LIME, MAGENTA (of FUCHHSIA), MAROON, NAVY, OLIVE, ORANGE, PURPLE, RED, SILVER, TEAL, WHITE en YELLOW.

gc.setStroke(Color.RED);

gc.setFill(Color.NAVY);

Naast de 15 basiskleuren zijn er nog ruim honderd gedefinieerde kleuren.
Kijk daarvoor in de JavaFX documentation.

Wil je toch zelf een kleur samenstellen dan kan dat ook.
Je moet daarvoor een instantie van de klasse Color maken.

Color mijnkleur = Color.rgb(0,130,132);
gc.setStroke(mijnkleur);

Het eerste argument de roodwaarde, het tweede argument de groenwaarde en het derde argument de blauwwaarde, elk uit een reeks van 0 tot en met 255.

★ Aan de slag 32

Bij deze opdrachten moet het canvas leeg gemaakt worden.
Dat kan met de methode clearRect(x1,y1,x2,y2).
x1,y1 geven de linkerbovenhoek van het canvas aan en x2,y2 de rechteronderhoek.

gc.clearRect(0,0,canvas.getWidth(),canvas.getHeight());

De methodes getWidth() en getHeight()geven respectievelijk de breedte en hoogte van het canvas.

  1. Maak een app die rode gevulde cirkel tekent als je op de cirkelknop klikt of een groenblauwe rechthoek RGB (0,130,132) tekent als je op de rechthoekknop klikt.
  2. Maak een app waarbij de gebruiker het aantal te tekenen cirkels invoert.
    De app tekent de cirkels vanaf één punt waarbij de omtrek van cirkels steeds groter wordt.
  3. Maak een app die een gekleurde spiraal tekent.
    Tip: gebruik een herhaling.  
  4. Maak een app die een schaakbord tekent.
    Tip: Maak gebruik van een herhaling horizontaal om afwisselend een open vierkant en een gevuld vierkant te tekenen.
    Teken verticaal de rijen met een tweede herhaling om de eerste herhaling.

 

Fonts

Het lettertype van een tekst kan aangepast worden met de methode setFont(Font).
Het argument van de methode is een object van de klasse Font, waarbij met behulp van de methode font(naam, stijl, stand, grootte)het lettertype aangepast wordt.

gc.setFont(Font.font("Dialog", FontWeight.NORMAL, FontPosture.ITALIC, 12));

Het eerste argument in de methode font() is het lettertype dat gebruikt wordt, bijvoorbeeld Arial, Comic Sans MS, Courier, Helvetica,  SansSerif, Tahoma, Times New Roman, Verdana.
De lijst is veel groter, maar deze lettertypen zullen op alle computersystemen ondersteund worden.
Het standaardlettertype dat gebruikt wordt is Dialog.

De stijl van de letter wordt aangepast met een attribuut van de klasse FontWeight:

BLACK, BOLD, EXTRA_BOLD, EXTRA_LIGHT, LIGHT, MEDIUM, NORMAL, SEMI_BOLD, THIN

De stand, of een letter cursief of rechtop staat, bepaalt het attribuut van de klasse FontPosture: ITALIC, REGULAR.

Het laatste argument geeft de grootte van de letter aan.

Om de klassen Font, FontWeight en FontPosture te kunnen gebruiken moet het package javafx.scene.text geïmporteerd worden.

★ Aan de slag 33

  1. Maak een app die de letters van het woord DIAGONAAL diagonaal met stijl EXTRA_BOLD afbeeldt.
  2. Maak een app die de letters van het woord SCHREEUW steeds groter afbeeldt.

VerkeerslichtApp

In de app hiernaast zie je een verkeerslicht dat bediend wordt door het klikken op een knop.

Hiervoor schrijven we een aparte klasse Verkeerslicht.
De constructor krijgt als argument de positie van de linkerbovenhoek van het verkeerslicht mee:
public Verkeerslicht(int xpos, int ypos)

De klasse Verkeerslicht kent de volgende methodes:

public void tekenVerkeerslicht(GraphicsContext gc)
Deze methode tekent het verkeerslicht.

public void setRood (GraphicsContext gc)
Deze methode zet het rode licht aan en het oranje licht uit.

public void setOranje(GraphicsContext gc)
Deze methode zet het oranje licht aan en het groene licht uit.

public void setGroen(GraphicsContext gc)
Deze methode zet het groene licht aan en het rode licht uit.

Hier vind je de code van de klasse Verkeerslicht.

★ Aan de slag 34

  1. Schrijf de klasse Verkeerslicht.
  2. De VerkeerslichtApp heeft een knop Schakel waarvoor een event-handler geschreven moet worden.
    Een paar tips:
  • Creëer een instantie van de klasse Verkeerslicht.
  • Creëer een variabele status die registreert welk licht brandt.
  • In de methode start() wordt het verkeerslicht getekend en het licht op rood gezet. Dat is de beginsituatie.
  • In de event-handler wordt de kleur van het verkeerslicht gewijzigd: rood -> groen -> oranje -> rood enzovoort.

    Schrijf de Verkeerslichtapp.

★ Aan de slag 35

  1. In de klasse Verkeerslicht krijgt het verkeerslicht een bruine kleur:

    Color BRUIN = Color.rgb(110,75,40);
    gc.setFill(BRUIN);
    Het bovenste licht krijgt de kleur rood:
    gc.setFill(Color.RED);

    Waarom staat er voor BRUIN als argument bij gc.setFill() geen Color en bij RED wel?
     
  2. Waarom moet er een object van de klasse GraphicsContext gecreëerd worden?

★ Aan de slag 36

Hiernaast zie je een app dat een eenvoudig huisje tekent.
Voor de app moet de volgende methode geschreven worden:

public void tekenHuis(int x, int y)  {

}

x en y zijn de coördinaten, die de linkerbovenkant van het vierkant in het huisje aangeven.

  1. Schrijf de app volgens de bovenstaande specificaties.
  2. Sla de app op onder de naam HuisApp.

★ Aan de slag 37

  1. Pas de HuisApp aan, zoals bij het voorbeeld hieronder.
    Daarvoor hoef je alleen de methode tekenHuis() aan te passen.
  2. Een aantal huisjes tezamen vormen een straat.
    De StraatApp kan gemaakt worden met behulp van de methode tekenHuis().
    Gebruik een for -loop (of een while -loop) om vijf huisjes te tekenen.

 

Enigmabord

Het maken van software gebeurt meestal in teamverband.
In deze opdracht moet je een onderdeel van de game Enigmabord maken.

Het spel lijkt op het oude ganzenbord.
Twee spelers gooien om beurten de dobbelsteen.
De pion mag het aantal vakjes van de worp vooruit.
Komt een speler op Alan Turing dan mag hij hetzelfde aantal ogen vooruit of tweemaal het aantal ogen achteruit.
Er zijn ook nog speciale afbeeldingen.
De betekenis van iedere afbeelding verschijnt onder in het mededelingVeld.
Diegene die het eerst precies op 61 (de Enigma) komt, heeft gewonnen.

Door het team zijn al een aantal klassen geschreven.
Ook is het ontwerp van de app al klaar.

Deze klasse Bordspel heeft de volgende methoden:

  • public void tekenSpeelVeld (Pane root)
    Deze methode tekent het speelbord.
  • public void teken(Pane root, GraphicsContext gc, Canvas c)

    Deze methode tekent de pionnen en de dobbelsteen.
    Na iedere worp moeten de pionnen en de dobbelsteen opnieuw getekend worden om de nieuwe score van de dobbelsteen en de nieuwe positie van de pionnen op het speelveld te tonen.

  • public void startSpel()
    Deze methode zet alles klaar, zodat het spel kan beginnen.
  • public void spelerGooit()
    Deze methode laat de speler die aan de beurt is dobbelen.
  • public String checkWorp()
    Deze methode analyseert de worp.
    Het resultaat van deze methode is een String, die een mededeling geeft aan de spelers, bijvoorbeeld een beurt overslaan.
  • public void verplaatsPion()
    Deze methode verplaatst de pion van de speler die gegooid heeft.

Op de interface staan twee knoppen:
Start: de pionnen worden klaargezet en het spel kan beginnen.
Dobbel: de speler die aan de beurt dobbelt en de worp wordt verder afgehandeld.

★ Aan de slag 38

  1. Download het zipbestand Enigmabord en pak het bestand uit op je computer.
  2. Definieer in de EnigmabordApp een instantie van de klasse Bordspel.
  3. Schrijf de event-handlers en de overige code voor de App.
    Je mag de interface niet wijzigen!
  4. Sla de app op.

Grafische dobbelsteen

In deze opdracht leer je hoe je met behulp van een nieuwe klasse GraphDobbelsteen een app kunt schrijven die de worp van een dobbelsteen in een afbeelding weergeeft.
De nieuwe klasse GraphDobbelsteen is een uitbreiding van de al eerder geschreven klasse Dobbelsteen:

import javafx.scene.canvas.*;
public class GraphDobbelsteen extends Dobbelsteen {


}

Omdat de klasse GraphDobbelsteen een uitbreiding(extends)van de bestaande klasse Dobbelsteen is, krijgt de klasse door overerving de methoden dobbel() en getWorp().
In de klasse Dobbelsteen is het attribuut aantalOgen private gedeclareerd.
Daardoor is dat attribuut alleen beschikbaar in die klasse.
Om het attribuut beschikbaar te maken in de klasse GraphDobbelsteen zou de toegang public gemaakt kunnen worden, maar dan is het overal beschikbaar.
We willen de gegevens zoveel mogelijk verborgen houden (data-hiding).
Daarom maken we de toegang protected, dat wil zeggen dat de alleen subklasse GraphDobbelsteen toegang krijgt tot het attribuut aantalOgen in de superklasse Dobbelsteen.

★ Aan de slag 39

  1. Kopieer de klasse Dobbelsteen naar de map waarin je de GraphDobbelApp gaat maken.
  2. Maak het attribuut aantalOgen in de klasse Dobbelsteen protected.

De klasse GraphDobbelsteen krijgt een methode om de dobbelsteen te tekenen: tekenSteen().
Deze methode heeft de onderstaande interface:

public void tekenSteen(int x, int y, GraphicsContext gc, Canvas c)

x en y zijn de coördinaten, die de linkerbovenkant van de dobbelsteen aangeven.
gc is het object dat het grafisch venster representeert.

De klasse GraphDobbelsteen heeft de onderstaande vorm:

import javafx.scene.canvas.*;
public class GraphDobbelsteen extends Dobbelsteen {

public void tekenSteen(int x, int y, GraphicsContext gc, Canvas c) {
     gc.clearRect(0,0, c.getWidth(),c.getHeight());
     gc.strokeRoundRect(x, y, 150, 150, 30, 30);    
}

★ Aan de slag 40

Schrijf de code die ogen van de worp tekent.
Het aantal ogen dat getekend moet worden, ligt vast in het attribuut aantalOgen.

 

★ Aan de slag 41

Nu kan het applet geschreven worden.
Met behulp van het designformulier wordt de interface ontworpen.

  1. Ontwerp een interface voor GraphDobbelApp zoals in het voorbeeld.
  2. Importeer het package canvas: javafx.scene.canvas.*
  3. Declareer en creëer een instantie van Canvas en GraphicsContext.
  4. Declareer en creëer een instantie van GraphDobbelsteen.
  5. Voeg het canvas toe aan de Pane.
  6. Laat de Dobbelsteen tekenen in de methode start().
  7. Schrijf de event-handler van de DobbelKnop.
  8. Sla de app op.

Toets 1

In de volgende toets wordt getoetst wat je inmiddels zou moeten weten over het onderwerp Objectgeoriënteerd programmeren met JavaFX.

Maak de toets:

Objectgeoriënteerd programmeren, klasse Application en Tekenen

E Arrays

Inleiding

Tot nu toe heb je gewerkt met variabelen die op zichzelf staan:

int getal;
String naam;


Vaak zal het voorkomen dat gegevens niet los van elkaar staan, maar een reeks vormen.
Bijvoorbeeld een leerlingenlijst, een adreslijst of een catalogus van boeken.

De bovenstaande rij bevat de titels van boeken.

In Java kun je een dergelijke reeks vastleggen met behulp van een array.
Je kunt een array voorstellen als een rij (of kolom) met dezelfde soort gegevens, bijvoorbeeld een array met boektitels of een array met lottogetallen.
Een array is een object en moet daarom met de new-opdracht worden gecreëerd.
De items in de array worden elementen genoemd.
De elementen van een array moeten allemaal van hetzelfde type zijn.
Voor het “bundelen” van variabelen van verschillende type gebruik je een klasse.
Je verwijst naar een element via de bijbehorende positie in de array, de index.

Een array maken

Net als andere variabelen moeten arrays gedeclareerd worden:

  String[] boektitel;

Achter het woord String staan rechthoekige haakjes[].
Daarmee wordt aangegeven dat het om een referentie naar een array van Strings gaat en niet naar een gewone String.

De volgende stap is de creatie van de array.
Daarbij geef je het maximaal aantal elementen op dat de array kan bevatten:

  boektitel = new String[4];

In het array-object boektitel kunnen nu maximaal 4 boektitels worden opgenomen.
Let op! De indices lopen hierbij van 0 tot en met 3.
Natuurlijk kunnen de declaratie en de creatie ook in één statement worden samengenomen:

  String[] boektitel = new String[4];

Schematisch zou je deze array als volgt kunnen voorstellen:

★ Aan de slag 42

  1. Maak de volgende opgaven
    1. Wanneer gebruikt een programmeur een array om gegevens op te slaan?
    2. Wat is de index van een array?
    3. Wat is een element van een array?
  2. Hoe maak je in Java een array met 10 objecten van de klasse TextField?

Een array vullen

De elementen van de array kunnen gevuld worden door middel van een toekenning:

boektitel[0] = "Turks Fruit";
boektitel[1] = "Het verdriet van België";
boektitel[2] = "De aanslag";
boektitel[3] = "De buitenvrouw";


Door gebruik te maken van een index is het gebruik van een array erg handig.
In het volgende voorbeeld wordt de boekenlijst afgebeeld op een app.
Daarvoor maken we gebruik van een instantie van de klasse ListView (boekenLijst).
De interface van de app bevat daarnaast een instantie van de klasse Button (toonKnop).



Als eerste wordt de array gedeclareerd en gecreëerd:

public class Boekenlijst extends Application {
  private int AANTAL = 4;
  private String[] boektitel = new String[AANTAL];
  private String[] boekauteur = new String[AANTAL];

In de event-handler van de toonKnop worden de elementen gevuld met de titels van de boeken en de daarbij behorende schrijvers.
Met behulp van het for-statement wordt langs alle elementen van de array gelopen.
Om elementen aan de boekenLijst (ListView) toe te voegen wordt de lijst van elementen van de boekenLijst opgevraagd met de methode getItems().
Met behulp van de methode add() kan een element aan die lijst worden toegevoegd.

Deze methode krijgt een argument mee en geeft geen resultaat:

getItems().add(String)

Het argument is het item dat toegevoegd moet worden aan de lijst.

public void toonKnopActionPerformed(ActionEvent evt) {
  boektitel[0] = "Turks Fruit";
  boektitel[1] = "Het verdriet van België";
  boektitel[2] = "De aanslag";
  boektitel[3] = "De buitenvrouw";
  boekauteur[0] = "Jan Wolkers";
  boekauteur[1] = "Hugo Claus";
  boekauteur[2] = "Harry Mulisch";
  boekauteur[3] = "Joost Zwagerman";
  for (int t = 0; t < AANTAL; t++) {
     boekenLijst.getItems().add(boektitel[t]
+ " - " + boekauteur[t]);
  }
}// end of toonKnop_Action

★ Aan de slag 43

  1. In de event-handler van de toonKnop staat een for-statement:
    for (int t=0; t < aantal; t++)
    Waarom staat er als tweede argument t < aantal en niet t <= aantal ?
  2. In de body van het for-statement staat de methode-aanroep boekenLijst.getItems().add(boektitel[t] + " - " + boekauteur[t]);
    Deze methode heeft een argument.
    Welke waarde geeft het argument door aan de methode?
  3. Maak de BoekenlijstApp.

 

Zoeken in een array

Een belangrijk voordeel van arrays is dat je er heel makkelijk iets in kunt opzoeken.
In het voorbeeld van het ZoekMaximumApp wordt het grootste getal gezocht in een lijst van 10 willekeurig gegenereerde getallen.
De interface van de app bevat een instantie van de klasse Button, de klasse Label en de klasse ListView.
De array bevat een lijst met int-waarden.
Die maak je in principe op dezelfde manier als een array met strings:

public class ZoekMaximumApp extends Application {
  private int AANTAL = 10;
  private int[] intRij = new int[AANTAL];


De event-handler van de Maximum-knop zorgt ervoor dat de elementen worden gevuld met int-waarden.
Vervolgens wordt in de array de hoogste waarde gezocht:

public void maximumKnop_Action(Event evt) {
  intLijst.getItems().clear();
  for (int t = 0; t < AANTAL; t++) {
     intRij[t] = (int)(Math.random()*100);
     intLijst.getItems().add(String.valueOf(intRij[t]));
  }
  int maximum = intRij[0];
  for (int t = 1; t < AANTAL; t++) {
     if (maximum < intRij[t])
         maximum = intRij[t];
  }
  uitvoerLabel.setText(String.valueOf(maximum));  
  } // end of maximumKnop_Action

 

Als eerste worden alle items uit intLijst (een instantie van de klasse ListView) verwijderd:

    intLijst.getItems().clear();

In het eerste for-statement wordt een lijst van 10 int-waarden gegenereerd.
Daarvoor wordt gebruik gemaakt van de methode random() uit de klasse Math.
Deze waarden worden opgeslagen in de array intRij.
Met behulp van de methode add() worden de elementen vervolgens in de lijst op de app geplaatst.

Dan wordt er een variabele maximum gedeclareerd en geïnitialiseerd met de waarde van het eerste element.

Vervolgens worden in het tweede for-statement de overige elementen van de array afgelopen om te zien of er een grotere waarde is dan de waarde van maximum.
Is dat het geval dan wordt de waarde van maximum vervangen door die van het actuele element.
Wanneer alle elementen de revue gepasseerd zijn wordt de waarde van maximum op het scherm gezet.

★ Aan de slag 44

  1. De event-handler van de maximumKnop kent twee for-statements.
    1. Leg in eigen woorden uit wat er in de eerste lus gebeurt.
    2. Leg in eigen woorden uit wat er in de tweede lus gebeurt.
  2. Maak de ZoekMaximumApp.

Zoeken naar een waarde

Stel dat je in de boekenlijst wilt zoeken of een bepaald boek aanwezig is.
Wanneer dat het geval is, moet de app de titel geven.
Anders moet er een mededeling verschijnen dat het boek niet gevonden is.

Voor het zoeken wordt een methode zoek() gebruikt.
Deze methode bestaat uit een for-statement die de hele array afloopt op zoek naar de gevraagde titel (een string).
Zodra die gevonden is, levert de methode door middel van het statement
return titel + “ gevonden!”; de gevraagde titel op en stopt de methode.
Als de titel niet wordt gevonden dan komt de methode uiteindelijk terecht bij het statement return “Titel ” + titel + “ niet gevonden”;.

public String zoek(String[] boekRij, String titel) {
  for(int t = 0 ; t < boekRij.length; t++) {
    if (boekRij[t].equals(titel))
      return boekRij[t] + “ gevonden!”;
  }
  return "Titel "+ titel+ " niet gevonden!";
}


Het zal vaak voorkomen dat je in een programma de bewerking op een array door een methode wilt laten doen.
De array wordt dan als argument aan de methode meegegeven.
In de methode zoek() wordt gezocht naar een String in een array, die als argument van de methode is meegegeven: boekRij.

Het woord length is een veld van een array-object, dat de lengte van de array oplevert.
Een lengte van een array is in het programma niet meer te wijzigen.
Je kunt alleen de lengte opvragen.
Wanneer je een programma schrijft, moet je van tevoren bepalen hoe groot de array is, die je nodig hebt.

Wanneer de interface gemaakt is, de array gedeclareerd, gecreëerd en geïnitialiseerd is en de methode zoek() geïmplementeerd is, dan blijft het schrijven van de event-handler van de zoekKnop over.
Deze bestaat maar uit twee statements:

  • Een statement dat zorg draagt voor de invoer van de titel.
  • Een statement dat het resultaat van de methode zoek() op het scherm plaatst.

★ Aan de slag 45

  1. In de methode zoek() wordt de lengte van boekRij gegeven door boekRij.length.
    Stel dat naam een instantie is van de klasse String dan kun je de lengte opvragen door naam.length().
    Waarom staan er in het eerste geval geen () en in het tweede geval wel?
  1. De methode zoek() zoekt in een rij of een boektitel voorkomt.
    Wanneer de titel gevonden wordt dan zal de methode als resultaat een melding opleveren dat de titel gevonden is.
    De melding dat de titel niet gevonden is mag dan niet meer worden gegeven.
    Leg aan de hand van de code uit dat dat ook niet gebeurt.
     
  2. Maak de ZoekBoekApp.

★ Aan de slag 46

In de TurfNamenApp wordt een lijst van 20 namen bijgehouden in een array.
De lijst wordt afgebeeld op de app in namenLijst, een instantie van de klasse ListView.
De gebruiker voert een naam in en door op de knop Geef aantal naam verschijnt in het label achter de knop het aantal keer dat de naam in de lijst voorkomt.
Door op de knop Geef aantal letter te klikken verschijnt achter de knop het aantal keer dat een naam uit de lijst met dezelfde letter begint als de naam die is ingevoerd.

  1. Ontwerp een interface voor de TurfNamenApp zoals in het voorbeeld.
  2. Creëer een array naamRij.
  3. Schrijf de event-handlers van de twee knoppen.
  4. Sla de app op.

★ Aan de slag 47

In de StatistiekApp worden een aantal bewerkingen op een lijst met getallen uitgevoerd.
Daarvoor heeft de app vier knoppen.
Wanneer de app wordt gestart, is alleen de knop Maak Getallen actief.

Maak getallen
Deze knop genereert een lijst van 10 willekeurige getallen van 10 t/m 99.
Gebruik een array om de getallen op te slaan en plaats die getallen in de intLijst (een instantie van de klasse ListView).
Wanneer op de knop Maak Getallen wordt geklikt, worden de andere knoppen actief gemaakt.

Minimum
Geeft het kleinste getal uit de rij getallen en plaatst die in het minimumLabel.

Som
Geeft de som van alle getallen en plaatst de uitkomst in het somLabel.

Even
Geeft het aantal getallen uit de rij dat een even getal is en plaatst het resultaat in het evenLabel.

  1. Ontwerp een interface voor de StatistiekApp zoals in het voorbeeld.
  2. Creëer een array intRij.
  3. Schrijf de event-handlers van de vier knoppen.
  4. Sla de app op.

★ Aan de slag 48

De Lotto is een gokspel, waarmee je kans maakt op de Jackpot van € 4.000.000 of meer en de hoofdprijs van € 1.000.000.

Hoe werkt Lotto?
Lotto is het bekende spel van de genummerde gele balletjes. Dat zijn er 45 om precies te zijn.
Hiervan worden er elke zaterdag zeven getrokken. Zes “gewone” ballen en één “bonusbal”.
Daarnaast wordt er uit 6 verschillende Jackpotkleuren (groen, oranje, paars, geel, blauw en rood) één winnende Jackpotkleur getrokken.
De opdracht is een app schrijven die de uitslag van de Lotto bepaalt.
Het resultaat van de trekking verschijnt in trekkingsLijst, een instantie van de klasse ListView.

Er zijn 4 knoppen:

Trek Lottoballen
Deze knop “trekt” de 6 ballen uit 45 genummerde ballen en zet de uitslag in de trekkingsLijst.
In principe kan een bal niet voor een tweede keer getrokken worden.
De bal is immers uit de bak.
Wanneer je het jezelf makkelijk wilt maken, houd je daar geen rekening mee.
Als je echter een goede simulatie wilt maken, moet je dat gegeven wel verwerken.
Maak gebruik van een array om de getallen op te slaan.

Bepaal Bonusbal
Deze knop “trekt” de bonusbal uit 45 genummerde ballen en zet het bonusgetal in het bonusVeld, een instantie van de klasse NumberField.
De bonusbal kan natuurlijk niet een van de zes al getrokken ballen zijn.

Bepaal Jackpotkleur
Deze knop “kiest” de Jackpotkleur uit de kleuren groen, oranje, paars, geel, blauw en rood en zet de getrokken kleur in het kleurVeld, een instantie van de klasse TextField.
Zet de zes kleuren in een array.

Maak Leeg
Deze knop zorgt ervoor dat de trekkingsLijst, bonusVeld en kleurVeld leeg gemaakt worden.

  1. Ontwerp een interface voor de LottoApp zoals in het voorbeeld.
  2. Creëer een array bal waar de zes lottoballen in worden opgeslagen.
  3. Schrijf de event-handlers van de vier knoppen.
  4. Sla de app op.

★ Aan de slag 49 (verdiepen)

In de praktijk komen we vaker een tabel tegen dan een enkelvoudige rij. Denk daarbij aan een spreadsheet of een databasetabel.
In het volgende voorbeeld gaan we uit van een tabelstructuur.

In de app hiernaast zie je een cijferlijst waar de cijfers opgeslagen zijn in een array, die bestaat uit rijen en kolommen.
Dit wordt een geneste of tweedimensionale array genoemd.

De declaratie van de geneste array heeft de volgende vorm:

int MAXLEERLING = 8;
int MAXTOETS = 4;
int cijfer [][] = new int[MAXLEERLING][MAXTOETS];


De array cijfer heeft twee indexen:
MAXLEERLING:   geeft het aantal rijen weer
MAXTOETS:   geeft het aantal kolommen weer

  1. Welk cijfer is opgeslagen in cijfer[1][2]?
  2. Welk cijfer is opgeslagen in cijfer[4][2]?
  3. Welk cijfer is opgeslagen in cijfer[4][0]?
  4. Welk cijfer is opgeslagen in cijfer[0][0]?

★ Aan de slag 50 (verdiepen)

Bij het ontwerp van de interface van de app moet je rekening houden met de volgende punten:

  • De namen worden weergegeven in een object namenLijst, een instantie van de klasse ListView.
  • De cijfers worden weergegeven in een object cijferLijst, een instantie van de klasse ListView.
  • De volgnummers van de toetsen worden weergegeven in een object toetsenLabel, een instantie van de klasse Label.
  • Het invoerveld voor het toetsnummer is toetsNrVeld, een instantie van de klasse NumberField.
  • De velden waarin de gemiddelden staan zijn respectievelijk leerlingVeld en toetsVeld.

De andere objecten spreken voor zich.

Ontwerp de interface van de app.

★ Aan de slag 51 (verdiepen)

De volgende stap is het vullen van de array met de cijfers van de leerling.
Wij doen dit nu op een manier, die je docent in werkelijkheid niet zal doen, namelijk met de methode random() uit de klasse Math.
Het vullen van de array gebeurt tijdens het opstarten van de app.
Daarom vind je de code terug in de methode start() van de app.
NB. De leerlingen kunnen een cijfer krijgen van 3 tot en met 9.

for (int t1 = 0; t1 < MAXLEERLING; t1++) {
  String resultaat = "";
  for (int t2 = 0; t2 < MAXTOETS; t2++) {
    cijfer[t1][t2] = (int)(Math.random()*7)+3;
    resultaat = resultaat + " " + String.valueOf(cijfer[t1][t2]);
  }
  cijferLijst.getItems().add(resultaat);

}

De namen van de leerlingen worden daaronder in de methode start() geïnitialiseerd:

namenLijst.getItems().add("Alan");
namenLijst.getItems().add("Bill");
namenLijst.getItems().add("Jan");
namenLijst.getItems().add("Jack");
namenLijst.getItems().add("Larry");
namenLijst.getItems().add("Mark");
namenLijst.getItems().add("Serge");
namenLijst.getItems().add("Steve");
namenLijst.getSelectionModel().select(0);

  1. Leg uit wat er gebeurt in het binnenste for-statement:

    for (int t2 = 0; t2 < MAXTOETS; t2++)  {
      cijfer[t1][t2] = (int)(Math.random()*7)+3;
      resultaat = resultaat + "   " + String.valueOf(cijfer[t1][t2]);
    }

  2. Wat is de functie van het buitenste for-statement?
    for (int t1 = 0; t1 < MAXLEERLING; t1++)
  3. Neem de bovenstaande code over in de app.

★ Aan de slag 52 (verdiepen)

De laatste stap van de vorige oefening is het schrijven van de event-handlers voor de knoppen.
We kijken naar de event-handler van de leerlingKnop.

public void leerlingKnop_Action(Event evt) {
  leerlingVeld.setText("");
  toetsVeld.setText("");
  int index = namenLijst.getSelectionModel().getSelectedIndex();
  if (index != -1) {
  cijferLijst.getSelectionModel().select(index);
    int som = 0;
      for (int t = 0; t < MAXTOETS; t++) {
        som = som + cijfer[index][t];
      }
      double gemiddelde = (double)som/MAXTOETS;
    leerlingVeld.setDouble(gemiddelde)
  }
}}

In regel 3 in de code geeft de methode getSelectedModel().getSelectedIndex()de plaats van het geselecteerde element in de namenLijst.
Als er geen element geselecteerd is, levert deze methode de waarde -1 op.
In de volgende regel wordt gecontroleerd of er een element geselecteerd is.
Wanneer dat het geval is wordt door middel van cijferLijst.getSelectionModel().select(index) de juiste rij geselecteerd en vervolgens het gemiddelde bepaald.

  1. Neem de code voor de event-handler van de leerlingKnop over in de app.
  2. Schrijf zelf de code voor de event-handler van de toetsKnop.
  3. Test de app en sla haar op.

F Werken met arrays

De CD-app

We bekijken een toepassing van een array in een iets grotere app: de CdApp.
De app moet het mogelijk maken om een lijst met cd’s (en eventueel dvd's, blu-ray’s) samen te stellen.
De gebruiker van de app moet de mogelijkheid hebben om:

  • een cd te kunnen toevoegen aan de lijst;
  • een cd te verwijderen uit de lijst;
  • een cd te verplaatsen;
  • een cd opzoeken.

De cd’s worden geplaatst in cdLijst, een instantie van de klasse ListView.
De invoervelden heten artiestVeld en titelVeld.
De knoppen heten respectievelijk voegToeKnop, verwijderKnop, omhoogKnop, omlaagKnop, zoekArtiestKnop en zoekTitelKnop.

★ Aan de slag 53

Ontwerp de interface van de CdApp.

 

De CD-app - 2

We hebben te maken met twee gegevens die onlosmakelijk bij elkaar horen: de naam van de artiest en de titel van de cd.
Daarvoor maken we een aparte klasse CdDvd.

public class CdDvd {
  public String naam;
  public String titel;
}


De klasse CdDvd bevat twee velden voor het bijhouden van de gegevens en heeft verder geen methodes.
Van deze klasse heb je een reeks van instanties nodig om alle cd’s op te slaan.
Het ligt voor de hand om hiervoor een array te gebruiken.
We gaan ervan uit dat het programma vijftig cd’s moet kunnen bijhouden.
Als eerste moet je een naam declareren (referentie) voor de array:

private int MAXAANTAL = 50;
private CdDvd[] cdDvdRij = new CdDvd[MAXAANTAL];


De array bevat op dit moment alleen nog maar de referenties voor cdDvdRij.
(CdDvd is een referentietype zoals alle klassen, in tegenstelling tot primitieve typen zoals bijvoorbeeld int.)
Als laatste stap moet je de array vullen met objecten.
Dat gaat vaak het eenvoudigst door in de start-methode van de app na de componenten met een for-statement de array te initialiseren:

for (int t = 0; t < MAXAANTAL; t++)
  cdDvdRij[t] = new CdDvD();

★ Aan de slag 54

  1. Schrijf de klasse CdDvd.
  2. Voor de bibliotheek wordt een BoekenApp geschreven.
    De programmeur heeft een aparte klasse Boeken geschreven om de titel, schrijver en categorie van het boek bij te houden.
    Om de gegevens in de app vast te leggen wordt gebruik gemaakt van een array.
    Declareer en initialiseer een array van honderd objecten van de klasse Boeken.

Toevoegen

De volgende stap is het schrijven van de event-handlers van de verschillende knoppen.
Als eerste de event-handler van de voegToeKnop:

    public void voegToeKnop_Action(Event evt){
      cdDvdRij[aantal].naam = artiestVeld.getText();
      cdDvdRij[aantal].titel = titelVeld.getText();
      artiestVeld.setText("");
      titelVeld.setText("");
      cdLijst.getItems().add(cdDvdRij[aantal].naam+" – "+cdDvdRij[aantal].titel);
      cdLijst.getSelectionModel().select(aantal);
      aantal++;
    artiestVeld.requestFocus();
    }    


In de eerste twee regels worden de naam van de artiest en de titel van de cd uit de velden gelezen en vastgelegd in de velden naam en titel van de cdDvdRij.
De variabele aantal is een instance variabele, die aan het begin van de klasse is gedeclareerd en geïnitialiseerd:

   int aantal = 0;

In deze variabele wordt bijgehouden hoeveel cd’s er zijn vastgelegd in de array.

Verder staan er in deze event-handler twee methodes van de klasse ListView.
De methode getItems() toont een instantie van ObservableList die de huidige elementen in de lijst toont.
De methode add(String) van de klasse ObservableList voegt een element toe aan de lijst van elementen op de aangegeven positie.
De methode getSelection() geeft als resultaat een instantie van MultipleSelectionModel die het geïnstalleerde selectiemodel bevat.
De methode select(int) van de klasse MultipleSelectionModel plaatst de cursor op de aangegeven positie.

★ Aan de slag 55

  1. Maak de volgende opgaven
    1. Bekijk de event-handler van de voegToeKnop van de CdApp.
      In de eerste regel staat:
      cdDvdRij[aantal].naam = artiestVeld.getText();
      Waarom moet dat niet zijn:
      cdDvdRij[aantal+1].naam = artiestVeld.getText();
    2. Welke twee methoden van de klasse ObservableList komen in deze event-handler voor?
    3. Leg uit wat de methode doet.
    4. Welke methode van de klasse MultipleSelectionModel komt in deze event-handler voor?
    5. Leg uit wat de methode doet.
    6. Wat is de functie van de methode requestFocus() in de laatste regel?
  2. Schrijf de event-handler van de voegToeKnop.

Verwijderen

De code van de event-handler voor de verwijderKnop is:

public void verwijderKnop_Action(Event evt) {
  int index = cdLijst.getSelectionModel().getSelectedIndex();
  for (int i = index; i < aantal; i++) {
     cdDvdRij[i].setCdDvd(cdDvdRij[i+1]);
  }
  aantal--;
  cdLijst.getItems().clear();
  for (int i = 0; i < aantal; i++)
     cdLijst.getItems().add(cdDvdRij[i].naam + " - " + cdDvdRij[i].titel);
  cdLijst.getSelectionModel().select(index);
}


In de eerste regel staat de methode getSelectedIndex().
Deze methode heeft als resultaat een int die de index van het geselecteerde element in de lijst geeft.

★ Aan de slag 56

Bekijk de event-handler van de verwijderKnop van de CdApp.

  1. Het for-statement heeft als eerste argument int i = index.
    Waarom mag dat niet int i = 0 zijn?
  2. Welke methoden van de klasse Observablelist komen in deze event-handler voor?
  3. Leg uit wat de methoden doen.
  4. Welke methoden van de klasse MultipleSelectionModel komen in deze event-handler voor?
  5. Leg uit wat de methoden doen.

Verwijderen - 2

Door middel van het for-statement wordt het geselecteerde element uit de array overschreven door het volgende element.
Daarvoor breiden we de klasse CdDvd uit met een methode setCdDvd().
De methode krijgt als argument een instantie van de klasse mee:

public void setCdDvd(CdDvd c) {
  this.naam = c.naam;
  this.titel = c.titel;

}

In de methode staat het woord this.
Daarmee wordt aangegeven dat het atrribuut naam van het huidige object wordt gedoeld.

★ Aan de slag 57

De klasse CdDvd wordt uitgebreid met een methode setCdDvd():

  1. Van welk type is het argument van deze methode?
  2. Wat is de betekenis van het woord this?
  3. Leg uit wat er in het volgende statement gebeurt:
      this.naam = c.naam;
  4. Breid de klasse CdDvd uit met de methode setCdDvd.

Verwijderen - 3

In de for-loop worden alle elementen uit de array vanaf het geselecteerde element een plaats in de index opgeschoven.
Daarna wordt het aantal met 1 verlaagd omdat er een element verwijderd is uit de array.
Tenslotte wordt de lijst opnieuw gevuld met de nieuwe array.

★ Aan de slag 58

Schrijf de event-handler van de verwijderKnop.

Verplaatsen en zoeken

De volgende twee knoppen moeten het mogelijk maken om een element te verplaatsen.
Om bijvoorbeeld omhoog te verplaatsen verwisselen we het element met het element dat erboven staat.
Het algoritme gaat als volgt:

tijdelijk = element[index];
element[index] = element[index-1];
element[index-1] = tijdelijk;

★ Aan de slag 59

Om twee elementen in een lijst te verwisselen wordt gebruik gemaakt van een variabele tijdelijk.
Waarom wordt er gebruik gemaakt van een variabele tijdelijk?

Verplaatsen en zoeken - 2

We bestuderen de code van de event-handler voor de omhoogKnop:

public void omhoogKnop_Action(Event evt){
  if (aantal > 1) {
    int cdLijst.getSelectionModel().getSelectedIndex()
    if (index > 0)  {
       CdDvd tijdelijk = new CdDvd();
       tijdelijk.setCdDvd(cdDvdRij[index]);
       cdDvdRij[index].setCdDvd(cdDvdRij[index-1]);
       cdDvdRij[index-1].setCdDvd(tijdelijk);
       index--;
       cdLijst.getItems().clear();
       for (int i = 0; i < aantal; i++) {
          cdLijst.getItems().add(cdDvdRij[i].naam + " - " + cdDvdRij[i].titel);
       }
       cdLijst.getSelectionModel().select(index);
     }
  }
}


In het eerste if-statement wordt gecontroleerd of er wel meer dan één element in de lijst staat.
Het tweede if-statement controleert of er wel een element geselecteerd is.
Wanneer er geen element geselecteerd is levert de methode getSelectedIndex() als resultaat -1.

Vervolgens wordt er een instantie van de klasse CdDvd, genaamd tijdelijk, gecreëerd.
Met behulp van dit object worden de twee elementen verwisseld.
Als laatste wordt de lijst opnieuw gevuld met de nieuwe array.

★ Aan de slag 60

  1. Bekijk de event-handler van de omhoogKnop van de CdApp.
    1. Wat is de functie van het eerste if-statement?
    2. Wat is de functie van het tweede if-statement?
  2. Schrijf de event-handlers van de omhoogKnop en de omlaagKnop.
  3. In het onderdeel van deze module “Arrays -> Zoeken naar een bepaalde waarde” heb je geleerd hoe je een waarde kunt zoeken in een rij.
    Schrijf de event-handlers van de zoekArtiestKnop en de zoekTitelKnop.

★ Aan de slag 61

In de verschillende event-handlers staat steeds dezelfde code om de cdLijst te vullen:

    cdLijst.getItems().clear();
    for (int i = 0; i < aantal; i++)
         cdLijst.getItems().add(cdDvdRij[i].naam + " - " + cdDvdRij[i].titel);
    cdLijst.getSelectionModel().select(index);

  1. Schrijf voor de CdApp een methode public void vulLijst(int index) die er voor zorgt dat de cdLijst gevuld wordt.
  2. Vervang in de event-handlers de bovenstaande code door de nieuwe methode vulLijst().

G Sorteeralgoritmen

Inleiding

De cd’s worden in een willekeurige volgorde ingevoerd in de CdApp.
Daarom willen we een functionaliteit toevoegen: het sorteren van de lijst.
Om elementen in een lijst te sorteren, zijn er diverse algoritmen.
We zullen een viertal algoritmen nader bekijken:

  • Bubble sort
  • Selection sort
  • Insertion sort
  • Quicksort

Bubble sort

Het idee van bubble sort is dat je de lijst doorloopt en dat je steeds twee opeenvolgende elementen, die niet in de juiste volgorde staan ten opzichte van elkaar, verwisselt.
Na de eerste keer de lijst doorlopen te hebben, staat het “grootste” element in de rij onderaan.
Na de tweede keer staat ook het “een na grootste" element op de juiste plaats.
Zo bubbelt als bij een koolzuurhoudende drank de gesorteerde lijst langzaam omhoog.
De lijst wordt hierbij herhaaldelijk doorlopen.

Bekijk de video over het bubble sort algoritme.
Het bubble sort algoritme zou je op de volgende manier kunnen beschrijven:

zolang de lijst niet gesorteerd is
  doorloop het ongesorteerde deel van de lijst
    als de huidige naam verkeerd staat t.o.v. de volgende naam
        verwissel de namen

★ Aan de slag 62

Bekijk de volgende lijst met getallen:
23, 7, 18, 48, 11, 5, 37, 21.
Deze rij getallen wordt met behulp van het bubble sort algoritme gesorteerd van klein naar groot.

  1. Welk getal staat na de eerste cyclus op de juiste plaats?
  2. Na hoeveel cycli staat 23 op de juiste plaats?
  3. Hoe vaak moet de lijst doorlopen worden om de getallen gesorteerd te krijgen?

 

Bubble sort - 2

In Java ziet de programmacode voor het sorteren van een rij getallen met bubble sort er als volgt uit:

   public void bubbleSort(int[] rij) {
     int aantalGesorteerd = MAXAANTAL;
     boolean opVolgorde = false;
     while(!opVolgorde) {
       opVolgorde = true;
       for (int teller = 0; teller < aantalGesorteerd-1; teller++)
         if (rij=[teller] > rij[teller+1]) {
           int tijdelijk = rij[teller];
           rij[teller] = rij[teller+1];
           rij[teller+1] = tijdelijk;
           opVolgorde = false;
       }
       aantalGesorteerd--;
     }
   }

★ Aan de slag 63

Voor het sorteren van een rij getallen gaan we een app schrijven.
Als eerste ontwerpen we de interface van de app.
Op de app staan vijf knoppen: maakGetallenrijKnop, bubbleSortKnop, insertionSortKnop, selectionSortKnop en quickSortKnop.
Daarnaast is er een instantie van de klasse ListView, getallenLijst, waar de lijst met getallen komt te staan.
Tenslotte nog tijdVeld, een instantie van NumberField.

  1. Ontwerp de interface.

Door op Maak Getallenrij te klikken wordt een lijst van 50 willekeurige getallen geplaatst die kunnen liggen tussen 1 en 10.000.

  1. Creëer twee instance variabelen van het type int:
    MAXAANTAL en MAXGETAL.
    MAXAANTAL krijgt de waarde 50 en MAXGETAL de waarde 10000
  2. Maak een array getallenRij.
  3. Schrijf de event-handler voor de maakGetallenrijKnop.
  4. Neem de code voor de methode bubbleSort(int[]) over.
  5. Schrijf de event-handler voor de bubbleSortKnop. Maak daarbij gebruik van de methode bubbleSort(int[]).
  6. Test de knop.

Selection sort

Bij selection sort wordt een lijst opgesplitst in twee delen:
een gesorteerd deel (aanvankelijk leeg) en een ongesorteerd deel.
In het ongesorteerde deel zoek je het kleinste element dat je daarna in de nog ongesorteerde lijst zet.
Vervolgens zoek je het daaropvolgende kleinste element en zet je dit achter aan het gesorteerde gedeelte.
Dit herhaal je totdat alle elementen deel uit maken van het gesorteerde gedeelte van de lijst.

Bekijk de video over het selection sort algoritme.
Het selection sort algoritme zou je op de volgende manier kunnen beschrijven:

zolang de lijst niet gesorteerd is
  doorloop het ongesorteerde deel van de lijst
    zoek het kleinste deel uit het ongesorteerde deel
  plak het achteraan het gesorteerde deel

★ Aan de slag 64

Bekijk de volgende lijst met getallen:
23, 7, 18, 48, 11, 5, 37, 21
Deze rij getallen wordt met behulp van het selection sort algoritme gesorteerd van klein naar groot.

  1. Welk getal staat na de eerste cyclus op de juiste plaats?
  2. Na hoeveel cycli staat 23 op de juiste plaats?
  3. Hoe vaak moet de lijst doorlopen worden om de getallen gesorteerd te krijgen?

 

Selection sort - 2

In Java ziet de programmacode voor het sorteren van een rij getallen met selection sort er als volgt uit:

public void selectionSort(int[] rij) {
  for (int teller = 0; teller < MAXAANTAL; teller++ ) {
    int kleinste = teller;
    for(int loper = teller + 1; loper < MAXAANTAL; loper++) {
      if(rij[loper] < rij[kleinste]) {
        kleinste = loper;
      }
    }
    int tijdelijk = rij[teller];
    rij[teller] = rij[kleinste];
    rij[kleinste] = tijdelijk;
  }
}

★ Aan de slag 65

  1. Neem de code voor de methode selectionSort(int[]) over.
  2. Schrijf de event-handler voor de selectionSortKnop.
    Maak daarbij gebruik van de methode selectionSort(int[]).
  3. Test de knop.

Insertion sort

Bij insertion sort wordt de lijst ook opgesplitst in twee delen:
een gesorteerd deel (aanvankelijk leeg) en een ongesorteerd deel.
In dit geval neem je steeds een element uit het ongesorteerde deel van de lijst en voeg je dit op de juiste plaats toe aan het gesorteerde deel.

Bekijk de video over het insertion sort algoritme.
Het insertion sort algoritme zou je op de volgende manier kunnen beschrijven:

doorloop vanaf element 2 het ongesorteerde deel van de lijst
  pak het huidige element en zet het in tijdelijk
  schuif vanaf het laatste element in de gesorteerde lijst tot
  aan het element dat kleiner is dan tijdelijk

In Java ziet de programmacode voor het sorteren van een rij getallen met insertion sort er als volgt uit:

public void insertionSort(int[] rij) {
  for (int teller = 1; teller < MAXAANTAL; teller++ ) {
    int tijdelijk = rij[teller];
    int loper = teller - 1;
    while((loper >= 0) && (tijdelijk < rij[loper])) {
      rij[loper+1] = rij[loper];
      loper--;
    }
    rij[loper+1] = tijdelijk;
  }
}

★ Aan de slag 66

  1. Neem de code voor de methode insertionSort(int[]) over.
  2. Schrijf de event-handler voor de insertionSortKnop.
    Maak daarbij gebruik van de methode insertionSort(int[]).
  3. Test de knop.

Quicksort - Recursie

Bij Quicksort wordt gebruik gemaakt van een recursief algoritme.

Bij recursie is een onderdeel van de methode het opnieuw uitvoeren van de methode.

Hiernaast zie je als voorbeeld een recursieve afbeelding: een bureaublad met het programma Paint, waarin een afbeelding staat van een bureaublad met Paint enzovoort, enzovoort.

Dit idee is in een versimpelde vorm met recursie te tekenen in Java.

In de methode tekenVierkant wordt een vierkant getekend.
Als de zijde groter is dan 10 dan wordt de methode tekenVierkant in zichzelf aangeroepen met de nieuwe waarden voor x, y en zijde.
Als zijde kleiner is dan 10 dan stopt de recursie.

 

Quicksort - Fractal

Het is ook mogelijk om bij recursie de methode meer dan één keer aan te roepen.
Een voorbeeld daarvan is de app, die een fractal tekent.
Een fractal is een afbeelding die bestaat uit een voortdurende herhaling van hetzelfde figuur of patroon, bijvoorbeeld een vierkant.

 

★ Aan de slag 67

Om een idee te krijgen hoe een recursief algoritme werkt, kijken we naar de RenteApp uit de module Visueel Programmeren met JavaFX.
Om het programma het eindkapitaal te laten berekenen hebben we gebruik gemaakt van een iteratie (herhaling) met een while-loop of for-loop.
In plaats van een iteratie was een oplossing door middel van recursie mogelijk geweest.

Daarvoor schrijven we een recursieve methode berekenKapitaal.
De methode roept zichzelf aan om een nieuwe termijn te berekenen, totdat de laatste termijn is verstreken.

public double berekenKapitaal(double k, double r, int t) {
  double kapitaal = k + k * r / 100;
  if (t>1)
    return berekenKapitaal(kapitaal,r,t-1);
  else
    return kapitaal;
}

  1. Ontwerp de interface van de app
  2. Neem de code over in de app.
  3. Waarom is de voorwaarde voor de recursie t>1 en niet t>=1?
  4. Schrijf zelf de code voor de event-handler van de berekenKnop.
  5. Test de app en sla haar op.

Quicksort

Bij quicksort wordt de lijst gesplitst in twee delen, die ieder apart gesorteerd worden.
Het sorteren van ieder deel gebeurt ook weer met quicksort: recursief.
Dit procedé herhaalt zich totdat aan een bepaalde afbreekvoorwaarde wordt voldaan.
Bij quicksort stopt het sorteren als het te sorteren deel nog maar uit één element bestaat.

Bekijk de video over het quicksort algoritme.

 

★ Aan de slag 68

  1. Welke functie vervult de spil bij het quicksort algoritme?
  2. Wat is het kenmerk van een recursief algoritme?

Quicksort - 2

Het quicksort algoritme zou je op de volgende manier kunnen beschrijven:

Bepaal de spil
Als er meer dan één element is
    Doorloop de rij
    Wanneer een element in het bovenste deel goed staat
        ga naar het volgende
    Wanneer een element in het onderste deel goed staat
        ga naar het volgende
    Als niet alle elementen goed staan
        Verwissel het huidige element van het bovenste deel met
        het huidige element van het onderste deel
Als het bovenste deel nog niet gesorteerd is
    sorteer het bovenste deel
Als het onderste deel nog niet gesorteerd is
    sorteer het onderste deel

 

★ Aan de slag 69

In Java ziet de programmacode voor het sorteren van een rij getallen met quicksort er als volgt uit:

public void quickSort(int[] rij, int eerste, int laatste) {
  int naar_onder = eerste;
  int naar_boven = laatste;
  int spil = rij[(eerste+laatste)/2];
  if (eerste < laatste)
    while (naar_onder < naar_boven) {
      while (rij[naar_onder] < spil)
        naar_onder++;
      while (rij[naar_boven] > spil)
        naar_boven--;
      if (naar_onder <= naar_boven) {
        int tijdelijk = rij[naar_onder];
        rij[naar_onder] = rij[naar_boven];
        rij[naar_boven] = tijdelijk;
        naar_onder++;
        naar_boven--;
      } // end of if
    } // end of while
  if (eerste < naar_boven)
    quickSort(rij, eerste, naar_boven);
  if (naar_onder < laatste)
    quickSort(rij, naar_onder, laatste);
}

  1. Neem de code voor de methode quickSort(int[], int eerste, int laatste) over.
  2. Schrijf de event-handler voor de quickSortKnop. Maak daarbij gebruik van de methode quickSort(int[], int eerste, int laatste).
  3. Test de knop.

Snelheid

We hebben een viertal sorteeralgoritmen bekeken.
De vraag is of er een verschil in snelheid tussen deze vier algoritmen bestaat.
Om dit te testen voegen we een paar regels code toe aan het SorterenApplet, zodat we de tijd in milliseconden kunnen registeren die een algoritme erover doet om een lijst van 5000 getallen te sorteren.

★ Aan de slag 70

  1. Open de SorterenApp in de JavaEditor.
  2. Wijzig aan het begin van de app bij //Begin variabelen de waarde van
    MAXAANTAL: int MAXAANTAL = 5000;
  3. Voeg aan het begin van de app bij //Begin variabelen de volgende code toe:
    double NAAR_MS = 1000000;
  4. Pas de event-handler van de bubbleSortKnop aan:

      public void bubbleSortKnop_Action(Event evt) {
        long startTijd = System.nanoTime();
        bubbleSort(getallenRij);
        long eindTijd = System.nanoTime();
        double tijd = (eindTijd - startTijd)/ NAAR_MS;
        vulLijst();
        tijdVeld.setDouble(tijd);
      } // end of bubbleSortKnop_Action

  5. Test de knop.
  6. Pas op dezelfde manier de andere drie knoppen aan.
  7. Test alle vier de knoppen een aantal keren.
    Welke conclusie trek je uit de test.

★ Aan de slag 71

We zijn nu in staat om een sorteerfunctie te implementeren in de CdApp.
Omdat het een kleine lijst betreft kunnen we volstaan met het relatief eenvoudige bubble sort algoritme.

  1. Open de CdApp in de JavaEditor.
  2. Voeg twee knoppen toe aan de app: sorteerArtiestKnop en sorteerTitelKnop.

In Java ziet de programmacode voor het sorteren van de lijst op naam met bubble sort er als volgt uit:

   public void sorteerArtiestKnop_Action(Event evt) {
     int aantalGesorteerd = aantal;
     boolean opVolgorde = false;
     while(!opVolgorde) {
       opVolgorde = true;
       for (int teller = 0; teller < aantalGesorteerd-1; teller++)
         if (cdDvdRij[teller].naam.compareTo(cdDvdRij[teller+1].naam) > 0) {
           CdDvd tijdelijk = new CdDvd();
           tijdelijk.setCdDvd(cdDvdRij[teller]);
           cdDvdRij[teller].setCdDvd(cdDvdRij[teller+1]);
           cdDvdRij[teller+1].setCdDvd(tijdelijk);
           opVolgorde = false;
         }
       aantalGesorteerd--;
     }
     vulLijst(0);
   }

  1. Neem de event-handler van de sorteerArtiestKnop over.
  2. Schrijf de event-handler van de sorteerTitelKnop.

★ Aan de slag 72 (verdiepen)

In de app hiernaast wordt door middel van de knop Vul lijst een instantie van de klasse ListView gevuld met 30 verschillende getallen tussen de 10 en de 100.
Door middel van de knop Sorteer oplopend wordt de lijst van klein naar groot gesorteerd en de knop Sorteer aflopend sorteert van groot naar klein.
Gebruik om te sorteren het quicksort algoritme.
Pas het algoritme zo aan dat je met de quicksort methode zowel oplopend (ascending) als aflopend (descending) kunt sorteren.
De interface van de quicksort methode ziet er dan als volgt uit:

public void quickSort(int[] rij, int eerste, int laatste, boolean asc)

De variabele asc geeft aan of er oplopend (true) of aflopend (false) gesorteerd moet worden.

  1. Ontwerp de interface voor de SorteerApp.
  2. Neem de code voor de methode quickSort over (Aan de slag 69).
  3. Pas de code aan zodat je zowel oplopend als aflopend kunt sorteren.
  4. Schrijf de event-handlers voor de drie knoppen.
  5. Test de knoppen.

★ Aan de slag 73 (verdiepen)

Als toepassing kijken we naar een eenvoudige opzet van een cijferadministratie.
De gebruiker voert met behulp van de knop Voeg toe de naam van de leerling en het rapportcijfer in.
Een leerling moet uit de lijst verwijderd kunnen worden.
De lijst kan gesorteerd worden op naam en op cijfer.
Tevens kan het gemiddelde van de klas opgevraagd worden.

De interface bestaat uit drie invoervelden met labels, vijf knoppen, een lijst waarin de namen en de cijfers worden getoond.

  1. Ontwerp de interface.

De gegevens die we moeten bijhouden zijn de naam van de leerling en het rapportcijfer.
Daarvoor maken we een aparte klasse Leerling.

De klasse Leerling bevat twee velden voor het bijhouden van de gegevens.
Deze velden worden public gedeclareerd.
Daarnaast heeft de klasse heeft een methode:

void setLeerling(Leerling l)     Wijzigt de naam en het cijfer van de leerling

  1. Schrijf de klasse Leerling.

Van deze klasse heb je een reeks van instanties nodig om alle leerlingen op te slaan.
Het ligt voor de hand om hiervoor een array te gebruiken.
We gaan ervan uit dat het programma dertig leerlingen moet kunnen bijhouden.
Als eerste moet je een naam declareren (referentie) voor de array: leerlingRij.
Daarna maak je een nieuw array-object met behulp van new.

  1. Declareer de array leerlingRij.

De array bevat op dit moment alleen nog maar de referenties voor leerlingRij.
Als laatste stap moet je de array vullen met objecten.
Dat gaat vaak het eenvoudigst door in de start-methode van de app met een for-statement de array te initialiseren:

  1. Vul de array met objecten van de klasse Leerling.
  2. Schrijf de event-handlers van de knop Voeg toe en Verwijder.
    Schrijf een methode vulLijst() om de gevens in de lijst te zetten.
  3. Test de app.
  4. Schrijf de event-handlers voor de knoppen Sorteer naam en Sorteer cijfer.
    Gebruik hiervoor het selection sort algoritme.
  5. Test de app.
  6. Schrijf de event-handler voor de knop Gemiddelde klas.
  7. Test de app.

Toets 2

In de volgende toets wordt getoetst wat je inmiddels zou moeten weten over het onderwerp Objectgeoriënteerd programmeren met JavaFX.

Maak de toets:

Arrays, Werken met Arrays en Sorteeralgoritmen

Voortgang

Bekijk hier je voortgang

Keuzedeel

 


Docent kan klassen aanmaken en leerlingen volgen
Een docent kan op de profielpagina klassen aanmaken.
Als een docent dat gedaan heeft, kunnen de leerlignen zich aan de klas koppelen.
Als de leerlingen dat gedaan hebben, kan de docent de voortgang van de leerlingen volgen.

>> Profielpagina

 

  • Het arrangement Objectgeoriënteerd programmeren met JavaFX is gemaakt met Wikiwijs van Kennisnet. Wikiwijs is hét onderwijsplatform waar je leermiddelen zoekt, maakt en deelt.

    Auteur
    VO-content
    Laatst gewijzigd
    2020-03-18 16:49:47
    Licentie

    Dit lesmateriaal is gepubliceerd onder de Creative Commons Naamsvermelding-GelijkDelen 4.0 Internationale licentie. Dit houdt in dat je onder de voorwaarde van naamsvermelding en publicatie onder dezelfde licentie vrij bent om:

    • het werk te delen - te kopiëren, te verspreiden en door te geven via elk medium of bestandsformaat
    • het werk te bewerken - te remixen, te veranderen en afgeleide werken te maken
    • voor alle doeleinden, inclusief commerciële doeleinden.

    Meer informatie over de CC Naamsvermelding-GelijkDelen 4.0 Internationale licentie.

    Het thema 'Objectgeoriënteerd programmeren met JavaFX' is ontwikkeld door auteurs en medewerkers van Enigma-online. Fair Use In de modules van Enigma-online wordt gebruik gemaakt van beeld- en filmmateriaal dat beschikbaar is op internet. Bij het gebruik zijn we uitgegaan van fair use. Meer informatie: Fair use Mocht u vragen/opmerkingen hebben, neem dan contact op via de helpdesk VO-content .

    Aanvullende informatie over dit lesmateriaal

    Van dit lesmateriaal is de volgende aanvullende informatie beschikbaar:

    Eindgebruiker
    leerling/student
    Moeilijkheidsgraad
    gemiddeld
    Trefwoorden
    algoritme, app, arrangeerbaar, array, java, klasse, leerlijn, objectgeorienteerd, rearrangeerbare