Derde Delphi Programma – verkenning In deze opdracht gaan we een aantal typische componenten en gegevenstypen van Windows en Delphi verkennen. We bouwen een eenvoudige ‘rekenmachine’ en ondertussen leer je van alles. Eerst even een tip, als je dat nog niet wist: met de F12 toets van je toetsenbord kun je wisselen tussen de ‘form’ en de ‘bron code’ achter de form. 1. Start Delphi en klik in het menu op File, New, VCL Forms Application 2. Maak de form wat groter door te klikken op de rechteronderhoek en dan met naar rechtsonder te bewegen. 3. Voeg een TEdit toe. Deze vind je in de Tool Palette (rechtsonder in Delphi). 4. Voeg rechts van de eerste TEdit een tweede TEdit toe. 5. Onder de eerste TEdit voeg je een TCombobox toe. 6. Daaronder een TRadioGroup. In de Object Inspector ga je naar de categorie Localizable en dubbelklik je op Items. Daar voeg je drie opties toe: bijvoorbeeld eerste optie, tweede optie, derde optie. Deze verschijnen als ‘radio buttons’ in de TRadioGroup 7. En daaronder een TButton. 8. Voeg onderaan een TLabel toe. Zet in de Object Inspector (linksonder in Delphi) in de categorie Localizable, Font de Size op 16 i.p.v. op 8. 9. Je scherm ziet er dan ongeveer als volgt uit:
10. Keer terug naar de Tool Palette en scroll tot je Additional tegen komt. Klap deze categorie eventueel open door op het + teken te klikken. Hieronder vind je een TImage. Voeg deze ook toe, bijvoorbeeld onder de tweede TEdit. 11. Nu de TImage nog steeds geselecteerd is, ga je terug naar de Object Inspector. Klik nu in de weer bij de categorie Localizable, dan bij Picture. Daar staat none, maar als je dubbelklikt krijg je het volgende schermpje:
12. Hiermee kun je een plaatje (Picture) toevoegen aan je TImage. Een TImage is dus niks meer dan een component wat plaatjes toont. Je kunt er overigens ook op tekenen, maar het moet dan niet een JPG, maar een BMP bestand zijn. Klik op de Load button van de Picture Editor. 13. Het zou kunnen dat je plaatje te groot is of dat je de TImage te klein hebt gemaakt. Je kunt dan de TImage groter maken door met je muis een hoekje van de TImage te slepen. Maar je kunt in de Object Inspector ook naar de categorie Miscellaneous en daar bij Stretch de waarde false veranderen in true (door te dubbelklikken). 14. Nu is het tijd om de ‘rekenmachine’ interactief te maken. Eerst de ‘gewone mensentaal’ uitleg. Het is de bedoeling dat de gebruiker getallen invult in de twee TEdit componenten/objecten en middels de TComboBox of de TRadiogroup een keuze maakt welke berekening er gedaan moet worden. Als de gebruiker op de TButton klikt komt het resultaat in de TLabel te staan. De TImage kan een bijvoorbeeld een logo bevatten. 15. Hoe we dat technisch doen, is als volgt. Tekst die in een TEdit wordt getypt, wordt opgeslagen in de property (eigenschap, variabele) Text. De keuze bij de TComboBox en in TRadioGroup wordt opgeslagen in de property ItemIndex. De tekst in de TLabel wordt opgeslagen in de property Caption. 16. Het enige wat we dus hoeven te doen is het zo programmeren dat de waarde uit Edit1.Text en de waarde van TEdit2.Text worden gebruikt in een formule met de soort berekening gekozen in ComboBox1.ItemIndex. Dan moet de uitslag van deze berekening in de property Caption komen van TLabel. 17. Om dit voor elkaar te krijgen, moeten we reageren op een actie door de gebruiker, op een event dus. Dat hadden we kunnen doen zodra de gebruiker wat invult in Edit1 of Edit2, maar we kunnen dat ook doen als Button1 wordt geklikt. We kiezen voor het laatste.
18. Dubbelklik op Button1. Wat er dan gebeurt, is dat Delphi code aanmaakt in Pascal en dat de cursor tussen de begin en end in staat: procedure TForm1.Button1Click(Sender: TObject); begin end; 19. Zie nog even de tweede opdracht: “Delphi: eerste interactieve programma” bij de week van 15-21 januari, als je precies wilt weten wat er nu eigenlijk staat. 20. Zet de cursor voor de B van Begin. Druk op enter. 21. In de nieuwe regel die nu ontstaat moet je het volgende typen: var Resultaat:string; Waarde1, Waarde2:integer; 22. In Pascal (Delphi) is het nodig om van te voren je variabelen te declareren. Variabelen zijn geheugenruimtes met daarin een bepaalde waarde van een bepaald type. De computer reserveert nu 3 geheugenruimtes met als naam Resultaat (met daarin: tekst/woordjes), aarde1 en waarde2 (met daarin: hele getallen zoals -1,0,1,2….) Je kunt nu de inhoud van de geheugenruimtes opvragen of veranderen, door gebruik te maken van de namen (Waarde1/Waarde2/Resultaat). Declareren wil zeggen dat je aankondigt dat je een bepaalde variabele gaat gebruiken en dat deze van een bepaald gegevenstype is. Een gegevenstype (data type) is een categorie variabele. Elk gegevenstype heeft z’n voor- en nadelen. De nadelen zitten vooral in de grootte / snelheid van de geheugenruimte die het inneemt. Zie voor alle typen de website: http://www.delphibasics.co.uk/ByFunction.asp?Main=Types 23. In (Visual) Basic hoef je geen gegevenstypen van te voren te declareren. Je kunt gewoon nieuwe variabelen ter plekke bedenken. Voordeel: lekker makkelijk. Nadeel: lekker slordig. Slordigheid in programmeren kan leiden tot grote of stomme fouten. 24. Het woord Var zorgt er voor de Delphi/Pascal weet dat er nu variabelen worden gedeclareerd. Het woord Resultaat is een zelf verzonnen naam voor een variabele. Daar kun je dus zo’n beetje elk ander woord voor bedenken. Tip: maak liever lange duidelijke namen, dan korte namen waarvan je later niet meer weet wat je variabele inhoudt. Het woord string betekent dat Resultaat van het gegevenstype string is. Een string is een aaneenschakeling van 255 karakters (gegeventype Char, niet te verwarren met…). Oftewel: je kunt in variabele Resultaat een kleine zin kwijt. De ; (punt-komma) is een soort stopteken in Pascal. Het vertelt Delphi dat hierna of een nieuwe variabele wordt gedeclareerd of dat het woord begin wordt verwacht om aan te geven dat er een ‘blok’ code komt van een procedure of functie. 25. De variabelen Waarde1 en Waarde2 worden allebei gedeclareerd als integer. Een integer is een gegevenstype voor gehele getallen (dus geen komma’s, maar gewoon -1,0,1,2, etc.). De zin is weer afgesloten met een punt-komma. 26. Het mooiste (niet het snelste) is nu om een aantal functies te schrijven die de verschillende deeltaken verrichten, algoritmes dus. We lezen de twee waarden (input), voeren de berekening uit en het tonen de uitslag (output). Type daarom het volgende:
procedure TForm1.Button1Click(Sender: TObject); var Resultaat:string; Waarde1, Waarde2:integer; begin Waarde1 :=LeesWaarde(Edit1.Text); Waarde2 :=LeesWaarde(Edit2.Text); Resultaat:=BerekenResultaat(Waarde1,Waarde2); ToonUitslag(Resultaat) end;
27. Wat er nu staat is dat Waarde1 wordt veranderd in de uitslag van de functie die LeesWaarde heet. LeesWaarde krijgt zelf ook een waarde mee, namelijk de waarde uit Edit1.Text. Het idee er achter is dat we straks een eigen functie maken die LeesWaarde heet en die het getal uitleest dat in Edit1 is gemaakt. Maar stel dat er tekst in staat… 28. Daarna wordt Waarde2 op soortgelijke manier toegekend. Het toekenningsteken in Pascal is de := (dubbele punt met is teken). 29. Resultaat wordt eigenlijk op soortgelijke wijze toegekend. Alleen is daar een andere functie voor die we zelf gaan schrijven, BerekenResultaat. 30. Tot slot moeten we ook nog een procedure schrijven die ToonUitslag heet en die de waarde Resultaat meekrijgt. 31. Nog even het principe: we lezen eerst een waarde, dan nog een waarde, dan voeren we een berekening uit en dan komt de uitslag in beeld. 32. Nu maken we onze drie algoritmes. Deze moeten gedeclareerd worden net als variabelen. Alleen nu in de hoofdstructuur van je programma. Ga naar regel 20 van je code. Daar staat private { Private declarations } 33. Zet de cursor achter de laatste } (accolade geheten) en druk op enter. Je hebt nu een nieuwe regel gemaakt (regel 21) waarin we de algoritmes kunnen declareren. Delphi kent twee algoritmes: functies en procedures. Het verschil is klein. Een functie levert een waarde op, bijvoorbeeld een string of een integer. Een procedure geeft geen waarden terug. Zie je dat ToonUitslag alleen een waarde meekrijgt, maar verder niks terug geeft als resultaat (behalve op het scherm?). Maar LeesWaarde en BerekenResultaat moeten wel waarden teruggeven. Type het volgende: private { Private declarations } function LeesWaarde(Tekst:String):integer; function BerekenResultaat(EersteWaarde,TweedeWaarde:Integer):string; procedure ToonUitslag(UitslagBerekening:String); 34. We declareren hier o.a. de functie LeesWaarde. Deze moet een waarde meekrijgen die we Tekst hebben genoemd. En LeesWaarde levert als uitslag een integer terug.
35. Klik nu met de rechtermuisknop op LeesWaarde en kies Complete Class at Cursor. Delphi schrijft automatisch de code die nodig is om (verderop) de details van alle drie algoritmes in te kunnen typen. 36. Zoek de functie LeesWaarde op, bijvoorbeeld op regel 53. Zet de cursor tussen Begin en End; en spring twee spaties in (voor ordelijkheid). Type het volgende: Result:=StrToInt(Tekst) 37. Je hebt aangegeven dat het resultaat van je functie de uitslag moet zijn van StrToInt(Tekst). StrToInt is een functie die in Pascal al bekend is. Het zorgt er voor dat een String wordt vertaald naar een Integer. Als dus iemand “0123” heeft ingetypt, zal het resultaat het getal (de integer) 123 zijn. 38. Zet nu de cursor tussen de begin en end; van de functie BerekenResultaat en type het volgende: Result:=IntToStr(EersteWaarde+TweedeWaarde) 39. Nu heb je gezegd dat het resultaat van de functie moet zijn het optellen van de inhoud 40. van de variabelen EersteWaarde en TweedeWaarde. En dan meteen een vertaling maken van een getal naar tekst dus van integer naar String. 41. Ho wacht eens! We zouden de gebruiker toch verschillende berekeningen laten kiezen en nu doen we alleen optellen? Ja, nu even wel, later gaan we de functie BerekenResultaat uitbreiden. 42. Zet nu de cursor tussen de begin en end; van de functie ToonUitslag en type het volgende: Label1.Caption:= UitslagBerekening 43. We hadden de uitslag natuurlijk spectaculairder kunnen maken, maar daar ben je vrij in. 44. Laten we het eens testen. Druk op F9 en voer wat waarden in, druk op de knop. 45. Als het ‘goed’ is, krijg je foutmeldingen als je bij Edit1 of Edit2 tekst ingevuld hebt. Dat is natuurlijk niet netjes. Daarom gaan we dat aanpassen. Sluit het programma, dan keer je automatisch terug in Delphi. 46. Ga in de bron code naar de functie LeesWaarde en verander de bron code als volgt: function TForm1.LeesWaarde(Tekst: String): integer; begin If not TryStrToInt(Tekst,Result) then ShowMessage('U moet een getal invoeren, niet tekst.') end; 47. Wat hier staat is dat we een Als…Dan functie inbouwen. We testen m.b.v. de standaardfunctie TryStrToInt of de Tekst in een getal is om te zetten. Als dat zo is, wordt het getal in Result gestopt, oftewel zal de functie Leeswaarde een getal terug geven. 48. Let even op de NOT. We testen dus bij deze If…Then of TryStrToInt geen getal bevat. Als dat inderdaad zo is, wordt een boodschap op het scherm gezet m.b.v. de standaardfunctie ShowMessage. 49. Nu nog een slordigheid wegwerken. Druk op F12 om in de Form te komen en selecteer door 1x te klikken op de knop (Button1). Ga naar de Object Inspector (linksonder) en verander bij de categorie Action de property Caption in ‘Bereken’ of zoiets.
50. Dan komen we bij de verschillende berekeningen, want tot nu tellen we alleen op. Klik eens op Combobox1. Ga naar de Object Inspector en de categorie Localizable. Daar staat de property Items. Deze is van het type TStrings, d.w.z. dat Items een heleboel strings, teksten kan bevatten. Dubbelklik op het woord TStrings. Het volgende scherm verschijnt:
51. Type in de vier regels in zoals hierboven staan vermeld en klik op OK. 52. Druk op F12 om terug te keren naar de broncode en zoek de functie BerekenResultaat weer op. Verander de bron code in: function TForm1.BerekenResultaat(EersteWaarde, TweedeWaarde: Integer): string; begin if ComboBox1.Text='optellen' then Result:=IntToStr(EersteWaarde+TweedeWaarde); if ComboBox1.Text='aftrekken' then Result:=IntToStr(EersteWaarde-TweedeWaarde); if ComboBox1.Text='delen' then Result:=IntToStr(EersteWaarde div TweedeWaarde); if ComboBox1.Text='vermenigvuldigen' then Result:=IntToStr(EersteWaarde*TweedeWaarde); end; 53. Wat er staat is vier keer een Als…Dan vergelijking of de Tekst van ComboBox1 voldoet aan bijvoorbeeld ‘optellen’. Zo ja, dan worden EersteWaarde en TweedeWaarde opgeteld en komen ze in de variabele Result te staan. Enzovoorts. 54. Let op: delen doe je dus niet met het \ teken, maar met het woord DIV. Pascal gebruikt het \ teken voor getallen die van het gegevenstype real zijn (getallen waar je ook iets achter de komma kunt zetten, maar die langzamer zijn dan integers). DIV wordt gebruikt voor het delen van integers. Alleen zul je merken dat DIV afrondt naar beneden. 55. Start je programma met F9 en probeer eens met een 4 en een 2 de verschillende opties. 56. Het kan ook anders. Nu moesten we EXACT op hetzelfde woord testen bij de If…Then test als er in de Items van de ComboBox staan. Eén spelfoutje (zelf hoofdletters verkeerd) en je programma werkt niet! Het voordeel is dat de positie van de optie in de ComboBox niet uitmaakt voor je programma. 57. We hadden echter ook kunnen kijken wat er bij ItemIndex is gevonden. ItemIndex houdt de selectie bij van de items uit de ComboBox. Het eerste item (dus ‘optellen’) is item 0, de
tweede item 1, etcetera. Zie voor een alternatieve manier de broncode die in de ZIP staat. Er wordt daar met een CASE gewerkt, waarmee je snel waarden kunt testen van één variabele, in dit geval ComboBox1.ItemIndex. Werkt sneller, maar als volgorde van de items verandert, dan klopt de berekening niet meer.
Opdracht:
Ga de rekenmachine die Windows gratis meelevert nabouwen. De knoppen met opschriften in het rood en de knoppen bewerken, beeld, Help mag je weglaten.