Labo 2 Programmeren II L. Schoofs K. van Assche Gebruik Visual Studio 2005 om een programma te ontwikkelen dat eenvoudige grafieken tekent. Deze opgave heb je vorig academiejaar reeds in Java geïmplementeerd. Het is echter aan te raden dat je helemaal terug opnieuw begint. In de onderstaande opgaven geven we de verschillende stappen om tot een werkend programma te komen. Zorg voor voldoende documentatie en commentaar tussen je code. Vergeet niet het geheel aan je portfolio toe te voegen. 1. Maak een GUI om de eenvoudige grafieken te tekenen en de invoer van de gebruiker in te lezen. De architectuur van je programma hebben wij reeds voor jou gemaakt en is terug te vinden in figuur 1. Figuur 1: Het klassediagramma van het programma om eenvoudige grafieken te tekenen. Deze geeft de architectuur van het programma weer. Sleep een Panel naar je design en geef het de juiste afmetingen: zorg ervoor dat het panel vierkant is. Dit kan je het beste regelen aan de 1
hand van het eigenschappenvenster. Hier vind je de eigenschap Size die je op de juiste waarden kan zetten. Sleep een TextBox naar het design en zorg ervoor dat je meerdere lijnen kan uitvoeren. Als laatste zet je twee Buttons op je GUI: een Ok knop om de gegevens op het anel te tekenen en een Stop knop om je programma af te sluiten. Je kan de namen van de componenten terugvinden in het klassediagramma (figuur 1). In figuur 2 krijg je een impressie over hoe de GUI eruit moet zien. (a) Start van het programma (b) Tekenen van een grafiek Figuur 2: Een impressie van de grafische gebruikers interface. Voorzie de volgende event handlers: StopButton_Click, OkButton_Click en TekenPanel_Paint. Je kan de handler voor de Stop Button reeds invullen. Als op deze knop gedrukt wordt, moet het programma stoppen. Het design van je GUI is nu klaar. 2. Maak een klasse Parser met slechts één statische methode: HaalGetallen(). Deze statische methode krijgt een string mee als argument en geeft een rij floats terug. In de methode wordt de string opgedeeld in stukken, die op hun beurt omgezet worden naar getallen. Zorg ervoor dat in de string geen spaties aan het begin en het einde aanwezig zijn doe dit aan de hand van de methode Trim(). Het opsplitsen gebeurt aan de hand van de spaties, komma s of newlines die tussen de getallen staan (Split()). Loop over alle sub-strings met een for -lus en zet ze om naar float. Denk eraan dat het omzetten niet per se moet lukken: als de gebruiker een fout typt bijvoorbeeld. Je krijgt dan een FormatException die opgevangen moet worden. Wanneer er een exceptie voorkomt, teken je een MessageBox op het scherm met een duidelijke foutmelding (vergeet niet de namespace System.Windows.Forms in te lezen met het sleutelwoord using). Het is hier verantwoord om een statische methode te gebruiken, omdat alle informatie uit de parameter kan gehaald worden. Er is dus geen 2
extra informatie nodig uit een omringend object. Dit is één van de uitzonderingen waarbij je een statische methode mag gebruiken! Koppel deze statische methode aan de GUI. Telkens op de Ok knop geklikt wordt, lees je de invoer van de invoertextbox in en verwerk je die met de methode HaalGetallen() uit de klasse Parser. Je krijgt dan netjes een rij gegevens terug die je kan gebruiken om te tekenen. 3. Als laatste maak je een klasse Grafiek die een grafiek gaat tekenen. Aan de constructor van deze klasse geef je het panel mee en stockeer je het in een veld. Wat moet er gebeuren om getallen te tekenen: Veeg het panel schoon. Maak hiervoor een methode WisPanel() met volgende code: this.panel.creategraphics().clear(color.white); De achtergrond wordt dan ineens op de kleur wit gezet. Teken een assenkruis op het panel via methode TekenAssenkruis(). Zoek het minimum en het maximum van de rij getallen die getekend moet worden. Implementeer hiervoor de methodes Min() en Max(). Je kan hier gebruik maken van foreach. Normaliseer de rij getallen tussen nul en één gebruik makende van het minimum en het maximum. Dit doe je door van elk getal in de rij het minimale getal af te trekken en te delen door het verschil tussen het maximum en het minimum. Dit moet op deze manier gebeuren, omdat de oorsprong van het panel links bovenaan ligt. (getallen[i]-minimum)/(maximum-minimum); Teken de genormaliseerde rij getallen op het panel. Voor elk van deze onderdelen moet je een aparte methode implementeren. Kijk in figuur 1 voor de juiste namen van de methoden en hun teruggeefwaarde. Het tekenen van lijnen doe je aan de hand van GDI+. Dit pakket vind je terug in System.Drawing. Je moet eerst een Pen declareren die je gebruikt om te tekenen. Aan een pen geef je de kleur (uit de Color klasse) en de dikte in pixels mee: Pen pen = new Pen(Color.Black, 1); Om nu op een component te tekenen, moet je eerst een Graphics object hebben om mee te tekenen. Dit kan je bekomen door het aan 3
het desbetreffende component te vragen: CreateGraphics(). Dus je kan aan het panel een grafisch object vragen, maar dat kan ook van elk andere grafische component in het.net Framework. Eens je een Graphics object hebt, kan je lijnen beginnen tekenen aan de hand van de volgende methode: g.drawline(pen, x1, y1, x2, y2); Je geeft dus naast de pen ook de coördinaten van twee punten mee, waartussen de lijn getekend moet worden. Omdat je niet op de rand van het panel kan tekenen, moet je een zekere afstand van die rand afblijven. Declareer een constante waarde als veld in je klasse: OFFSET. Declareer deze constante als een int en zet hem op 4 (pixels). Je zal de constante moeten gebruiken tijdens het tekenen van lijnen en punten. Om het assenkruis te tekenen, moet je de hoogte en de breedte van het panel kennen. Dit kan je opvragen op de volgende manier: int height = this.panel.height; int width = this.panel.width; De Y-as moet aan de linkerkant getekend worden en de X-as helemaal onderaan het panel. Vergeet hierbij niet dat de oorsprong van het panel links bovenaan ligt. De pijlpunten van de assen moet je zelf maken aan de hand van twee kleine lijntjes. Nu moet je nog de gegevens op de grafiek tekenen. Het tekenen van de grafiek doe je in een rode kleur en met een pen-punt van één pixel. Het eerste dat je moet berekenen is de horizontale afstand tussen de punten (vaste interval op de X-as). We delen de breedte van het panel door het aantal punten dat we gaan tekenen. Vermits we niet helemaal op de rand beginnen te tekenen, moet je eerste OFFSET van de breedte aftrekken. Ook heb je geen afstand nodig voor het eerste punt dat je gaat tekenen, daarom trek je van het totaal aantal punten één af. Om de lijnen van je grafiek te tekenen heb je steeds de vorige en de huidige waarde voor de Y-as nodig. De y-waarde krijg je door de genormaliseerde getallen te vermenigvuldigen met de hoogte van het panel. Voor de x-waarden moet je steeds het vorige en het huidige punt in rekening brengen tijdens het tekenen: dus je gebruikt de huidige en de vorige index van de lus. Die index vermenigvuldig je met de afstand tussen twee punten. Vergeet ook niet dat je steeds de OFFSET bij de x-waarde moet bijtellen. Let er extra op dat je de juiste grenzen neemt voor je for-lus. 4
4. Om het programma af te werken moet je de klasse Grafiek nog aan de GUI koppelen. Telkens het panel hertekend wordt, moet de grafiek volledig hertekend worden. Dit moet ook gebeuren wanneer de gebruiker op de Ok knop klikt. Je kan dus het best de rij getallen en een object van de klasse Grafiek als veld declareren in de klasse die de Form gaat tekenen (zie figuur 1). Vul nu nog de juiste event handlers in en je programma is klaar! Vergeet niet de nodige documentatie en commentaar te schrijven. In de bovenstaande uitleg is het testen van de code weggelaten, maar dat lijkt ons dan ook een evidente zaak. 5