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

  6.1. Een formulier om te kiezen

We willen een programma maken waarbij je woordjes in kunt voeren met hun vertaling in het engels, frans of een andere taal.
Die woordjes worden vastgelegd in een bestand.
En dan kun je jezelf overhoren: er wordt steeds een woordje getoond en dan moet je de vertaling geven.

Als het programma wordt gestart dan wordt er alleen maar een menu getoond, zoals hier rechts. (Je kunt ook een professioneel menu maken, met een menubalk; daarover lees je in hoofdstuk 7 van Delphi).

Als je dan klikt op "Voer in", dan verschijnt er een nieuw formulier dat er uitziet zoals hieronder bij paragraaf 2.
We gaan ervan uit dat je maar met één woordjesbestand werkt, met de naam "woordjes.txt".
In hoofdstuk 7 van Delphi zie je hoe je verschillende woordjesbestanden kunt openen en/of bewaren.

We beginnen met het eerste formulier. Je zet er 3 "buttons" op, met de tekst zoals hierboven rechts.
Als naam van het formulier voer je in: frmMenu, en als opschrift (Caption): Menu
Verder doe je er nog niets mee.

  6.2 Nieuw formulier maken; woorden invoeren en bewaren; arrays

Klik in het menu op File, dan op New, en dan op Form.



Dan krijg je een tweede (leeg) formulier in beeld.
Standaard wordt dat "form2" genoemd, maar dat kun je veranderen.
Vul in het propertiesvenster voor dit formulier bij Name in : frmVoerin , en bij Caption : Woordjes invoeren
Zet er 2 labels met als opschrift Woord: en Vertaling: en 2 buttons met als opschrift OK en Stop op.
De naam van de OK-button verander je in cmdOK en de naam van de stop-button in cmdStop.
Verder zet je er twee tekstvensters op.
De bovenste geef je als naam txtWoord, en die daaronder geef je als naam txtVertaling


Als je woorden wilt invoeren en opslaan als je klaar bent met het invoeren, dan moet de computer alle woordjes onthouden.
Als er honderd woordjes zijn ingevoerd dan moet hij die alle honderd onthouden, en ook de vertaling er van.
Daar ga je natuurlijk niet 100 aparte variabelen-namen voor bedenken, je doet dat met een array zoals we dat ook in Pascal hebben gezien.
Je declareert een array "woord[....]", zodat in de variabele woord[1] het eerste woord wordt bewaard, in woord[2] het tweede woord, enz.
De opdracht daarvoor is: var woord: Array[1..100] of String;
Verder moeten ook de vertalingen van die woorden worden onthouden, dat doe je met de opdracht:
var vertaling: Array[1..100] of String;
Ook het aantal woordjes, dat is ingevoerd, moet worden onthouden. Daarvoor gebruiken we de variabele aantal

Dit moeten globale variabelen zijn, we declareren ze dus boven de regel met implementation, waar ook het formulier wordt gedeclareerd.

Bij procedure TfrmVoerin.FormCreate(Sender: TObject); zet je de volgende code:

procedure TfrmVoerin.FormCreate(Sender: TObject);

begin
        aantal := 0;
end;

Voer bij de OK-knop als event-handler het volgende in:

procedure TfrmVoerin.cmdOKClick(Sender: TObject);

begin
      // het woord met de vertaling wordt opgeslagen
      // in de variabele woord[..] en vertaling[..]

      aantal:=aantal+1;
      woord[aantal]:=txtWoord.Text;
      vertaling[aantal]:=txtVertaling.Text;
      // de editvensters worden leeg gemaakt
      txtWoord.Text := '';
      txtVertaling.Text := '';
end;

Voer bij de Stop-knop als event-handler het volgende in:

procedure TfrmVoerin.cmdStopClick(Sender: TObject);

var i: integer;

begin
      // het bestand wordt opgezocht
      assignFile(f,'woordjes.txt');
      // de schrijfwijzer wordt aan het begin van het bestand gezet
      REWRITE(f);
      // de woorden met de vertaling worden opgeslagen
      // in het bestand "woordjes.txt"

      for i := 1 to aantal do
      begin
            WRITELN(f,woord[i]);
            WRITELN(f,vertaling[i]);
      end;
      // het bestand wordt afgesloten
      CloseFile(f);
      // Het invoer-formulier wordt verwijderd
      frmVoerin.close;
end;


De tekstfile f moet je als globale variabele declareren, omdat hij in verschillende procedures wordt gebruikt.

Dus boven de regel met implementation komt: (het eerste staat er al)

var
      frmVoerin: TfrmVoerin;
      // declaratie van de file
      f:textFile;
      // globale rij-variabelen voor de woorden, vertalingen enz.
      // aantal geeft aan hoeveel woorden zijn ingevoerd

      woord, vertaling: Array[1..100] of String;
      aantal: integer;

  6.3 Een nieuw formulier tonen en weer verwijderen.

Ga dan terug naar het eerste formulier (Klik bovenaan op het tabblad unit1).
Zorg er voor dat je het ontwerpvenster in beeld hebt (klik onderaan op het tabblad design
Klik dan dus op frmMenu, en op View Form.

Dubbelklik in het formulier op de button met "Voer in", dan kun je de bijbehorende programmaregels invoeren.
Voer bij procedure TfrmMenu.cmdVoerinClick de volgende code in:

procedure TfrmMenu.cmdVoerinClick(Sender: TObject);
var
      formVoerin: TfrmVoerin;
begin
      frmVoerin.ShowModal;
end;

Dat heeft tot gevolg dat als je op die button klikt het formulier met de naam "frmVoerin" wordt ingeladen en getoond.
En dat was de bedoeling !
Maar er moet meer gebeuren, anders werkt het nog niet.
Klik in het menu op File, en dan op Use Unit.
Voer in het venster, dat dan verschijnt unit 2 in, want de programmacode die bij frmVoerin hoort zit in unit 2.

Dan wordt aan de programmacode van unit 1 toegevoegd, onder implementation: uses unit 2;



Klik dan in het menu op Project, en dan op Options. Dan verschijnt het Options-venster (zie hieronder)
Daarin zie je (zie het venster hier onder) dat frmMenu het main form is, dat betekent dat bij het opstarten het formulier frmMenu getoond wordt.

Verder zie je onder Auto-create forms dat alle formulieren bij de start van het programma worden aangemaakt (in het geheugen). Als een programma uit veel formulieren bestaat dan neemt dat nogal wat geheugenruimte in beslag, en dan kun je de formulieren (behalve de eerste, want die moet er bij de start natuurlijk wel zijn) beter onder Available forms zetten. Dat doe je door op die formulieren te klikken, en dan te klikken op > tussen Auto-create forms en Available forms
Dan zijn de formulieren wel beschikbaar, maar bij de start nog niet gecreëerd.
Dan moet er, elke keer als zo'n formulier getoond moet worden, een extra opdracht bij voor de creatie voor het formulier.
De opdracht daarvoor is (bijv. voor het frmVoerin-formulier:



Als er op de stop-knop wordt geklikt moet het formulier verdwijnen. Daarom moet bij de procedure TfrmVoerin.cmdStopClick(Sender: TObject) o.a. de volgende regel code worden ingevoerd:
frmVoerin.close;

Dat heeft dus tot gevolg dat, als je op de stop-knop klikt, het invoer-formulier verdwijnt (en je kunt verder met het eerste, want dat staat er nog)

  6.4 Woorden inlezen, arrays

Als je jezelf wilt overhoren dan moet de computer allereerst de woordjes inlezen uit het bestand op de schijf.
En dan moet hij alle woordjes onthouden.
Als er honderd woordjes zijn ingevoerd dan moet hij die alle honderd onthouden, en ook de vertaling er van.
Daar gebruik je natuurlijk weer een array voor.
We gebruiken weer een array "woord[....]", zodat in de variabele woord[1] het eerste woord wordt bewaard, in woord[2] het tweede woord, enz.
En we gebruiken weer een array "vertaling[....]"
En dan moet de computer ook nog onthouden welke woorden al wel geweest zijn, en welke niet, want er moet natuurlijk niet twee keer het zelfde woord gevraagd worden.
Daarvoor heb je zogenaamde boolean-variabelen nodig, die alleen maar true of false kunnen zijn. Die variabele kunnen we bijv. geweest[....] noemen.
De opdracht daarvoor is: var geweest: Array[1..100] of Boolean;
Dit moeten allemaal globale variabelen zijn (ook die van de woordjes), we declareren ze dus boven de regel met implementation, waar ook het formulier wordt gedeclareerd.

We beginnen met het overhoorformulier, dat moet er uitzien als hiernaast.
Klik in het menu op File, dan op New, en dan op Form.

Dan krijg je weer een nieuw leeg formulier in beeld.
Vul in het propertiesvenster voor dit formulier het volgende in:
bij Name: frmOverhoor
bij Caption: Woordjes overhoren
Zet drie labels op het formulier met als opschrift Woord: en Vertaling: en Tot nu toe goed: en één met een 0.
Die labels noem je lblWoord, lblVertaling, lblGoed en lblAantalgoed
Zet er ook drie buttons op met als opschrift OK en Naar menu en Lees bestand in
De naam van de OK-button verander je in cmdOK
en de naam van de Naar-menu-button in cmdNaarmenu.
en de naam van de Lees-bestand-in-button in cmdLees.
Verder zet je er twee editvensters op.
De bovenste geef je als naam txtWoord
en die daaronder geef je als naam txtVertaling

In het begin moet alleen de knop met Lees bestand in zichtbaar zijn. Dus bij procedure TfrmOverhoor.FormCreate(Sender: TObject); zorg je er voor dat alle andere objecten onzichtbaar zijn.

Boven de regel met implementation, waar ook het formulier wordt gedeclareerd, zet je de volgende regels (de eerste staat er al):

var
      frmOverhoor: TfrmOverhoor;
      // globale rij-variabelen voor de woorden, vertalingen enz.
      // a is het nummer van het woord dat aan de beurt is

      woord, vertaling Array[1..100] of String;
      geweest: Array[1..100] of Boolean;
      aantalgoed, aantalgeweest, aantal, a: integer;
      // declaratie van de file
      f:textFile;

Bij procedure TfrmOverhoor.FormCreate(Sender: TObject); zet je de volgende programmaregels:

procedure TfrmOverhoor.FormCreate(Sender: TObject);

begin
      lblWoord.visible:=false;
      lblVertaling.visible:=false;
      lblGoed.visible:=false;
      lblAantalgoed.visible:=false;
      txtWoord.visible:=false;
      txtVertaling.visible:=false;
      cmdOK.visible:=false;
      cmdNaarmenu.visible:=false;
end;

Bij procedure TfrmOverhoor.cmdLeesClick(Sender: TObject); zet je de volgende programmaregels: (in de commentaarregels lees je het hoe en waarom)

procedure TfrmOverhoor.cmdLeesClick(Sender: TObject);

var i: integer;

begin
begin
      assignFile(f,'woordjes.txt');
      // de leeswijzer wordt aan het begin van het bestand gezet
      Reset(f);
      // We lezen alle woorden in met de bijbehorende vertalingen
      // tot het einde van de file is bereikt
      //
      // in het begin is nog geen enkel woordje aan de beurt
      // geweest, daarom: geweest(i):=false;

      i:=1;
      while not eof(f) do
      begin
            readln(f, woord[i]);
            if not eof(f) then readln(f, vertaling[i]);
            geweest[i] := false;
            aantal:=i;             i:=i+1;       end;
      aantalgoed := 0;
      aantalgeweest := 0;
      // de objecten moeten nu zichtbaar worden
      lblWoord.visible := true;
      lblVertaling.visible :=true;
      txtWoord.visible:=true;
      txtVertaling.visible:=true;
      cmdOK.visible:=true;
      cmdNaarmenu.visible:=true;
      lblGoed.visible:=true;
      lblAantalgoed.visible:=true;
      cmdLees.visible:=false;
      // zorgen voor willekeurige getallen
      randomize;
      // a moet een willekeurig getal tussen 1 en aantal zijn

      a := random(aantal)+1;
      // als a dan bijvoorbeeld 3 is dan wordt het derde woordje gevraagd
      txtWoord.text := woord[a];
      // de cursor wordt in het vertaal-venster geplaatst
      txtVertaling.setfocus;
      // en het derde woordje moet dan worden geregistreerd als
      // geweest zijnde, zodat het niet weer wordt gevraagd

      geweest[a] := true;

end;

Bij procedure TfrmOverhoor.cmdOKClick(Sender: TObject); zet je de volgende programmaregels:

procedure TfrmOverhoor.cmdOKClick(Sender: TObject);
begin
geweest[a] := true;
aantalgeweest := aantalgeweest + 1;

if txtVertaling.text=vertaling[a] then
begin
      ShowMessage('Goedzo');
      aantalgoed:=aantalgoed+1;
      lblAantalgoed.Caption:=IntToStr(aantalgoed);
end
else
begin
      ShowMessage ('Neen, het juiste antwoord is '+ vertaling[a]);
end;
if (aantalgeweest=aantal) then
      ShowMessage('Alle woorden zijn geweest')
else
while (geweest[a]=true) do
begin
      a := random(aantal)+1;
      txtWoord.text := woord[a];
      txtVertaling.Text := '';
      txtVertaling.setfocus;
end;
end;

en tenslotte zet je bij procedure TfrmOverhoor.cmdNaarmenuClick(Sender: TObject); de volgende code:

procedure TfrmOverhoor.cmdNaarmenuClick(Sender: TObject); begin // Het overhoor-formulier wordt verwijderd frmOverhoor.close; end;

  6.5 Opdrachten.

Opgaven.
Maak nu opgave 6 van de oefenopgaven van Delphi