8 Die "normale" Grafik:

Zum vorigen Kapitel Zum Inhaltsverzeichnis Zum nächsten Kapitel


Es gab auch schon Grafik in den verschiedenen Programmiersprachen, bevor die jeweiligen Turtle-Komponente geschrieben wurden.

Die "eigentliche" Delphi-Grafik wird über ein Objekt vom Typ "TCanvas" ("canvas" heißt auf deutsch: "Leinwand"!) abgewickelt. All die Delphi-Komponenten, auf denen User-Zeichnungen Sinn machen, haben eine solche Eigenschaft mit Namen Canvas. Für die Ausgabe von Grafiken eignet sich besonders eine PaintBox-Komponente, welche hauptsächlich aus einem "Canvas mit Rand" besteht.

Obwohl ein Canvas über viele schöne Zeichenbefehle verfügt (schauen Sie mal in der Online-Hilfe nach!), brauchen Sie für die folgende Aufgabe nur MoveTo(x, y) und LineTo(x, y), wobei die Integer(!)-Koordinaten x und y im Canvas-eigenen Pixel-Koordinatensystem interpretiert werden. Der Befehl zeichnet eine Strecke von der aktuellen Grafik-Cursor-Position zum Punkt Q(x, y).
Die "eigentliche" Java-Grafik wird über ein Objekt vom Typ "Graphics" abgewickelt. All die Java-Komponenten, auf denen User-Zeichnungen Sinn machen, haben ein solches Graphics-Objekt. Für die Ausgabe von selbsterstellten Grafiken auf der Oberfläche des Programms eignet sich besonders eine Canvas-Komponente, die einen rechteckigen Bereich für programmierte Zeichenoperationen zur Verfügung stellt -- und eben auch ein Graphics-Objekt, das die dazu nötigen Werkzeuge bereitstellt.

Obwohl ein Graphics-Objekt über viele schöne Zeichenbefehle verfügt (schauen Sie mal in der Online-Hilfe nach!), brauchen Sie für die folgende Aufgabe zunächst nur einen einzigen, nämlich drawLine(x1, y1, x2, y2), wobei die übergebenen Integer(!)-Koordinaten im Canvas-eigenen Pixel-Koordinatensystem interpretiert werden. Die Anweisung zeichnet eine Strecke vom Punkt P(x1, y1) zum Punkt Q(x2, y2).

Und hier beginnen die Probleme! Denn in den Zeiten, in denen der Computerbildschirm in Textzeilen von links oben nach rechts unten organisiert war, hat IBM einst festgelegt, dass auch der Grafik-Bildschirm seinen Ursprung in der linken oberen Ecke haben soll; die x-Achse zeigt tröstlicherweise nach rechts, die y-Achse aber leider nach unten(!). Von dieser Konvention konnte sich die ganze Programmierergemeinde bis zum heutigen Tag nicht lösen. Sowohl Delphi als auch Java setzen glücklicherweise den Ursprung des Pixel-Koordinatensystems von der linken oberen Ecke des Bildschirms in die linke obere Ecke des Canvas-Zeichenbereichs, aber für den Rest sind wir selbst verantwortlich.

Packen wir den Stier bei den Hörnern: was wir brauchen, ist eine Umrechnung der Koordinaten des PaintBox-Koordinaten-Systems in das User-Koordinaten-System - und umgekehrt! Wenn wir dies einmal erledigt haben, dann können wir beim Programmieren an jeder Stelle das jeweils am besten geeignete Koordinatensystem verwenden und nötigenfalls die Koordinaten einfach umrechnen. Der Zusammenhang zwischen den beiden Koordinatensystemen ist durch folgende Angaben geregelt:
Im User-Koordinatensystem sollen die Achsen die übliche Orientierung haben: die x-Achse zeigt nach rechts, die y-Achse nach oben. Während im PaintBox-Koordinatensystem immer mit ganzen Zahlen (Einheit ist 1 Pixel!) gerechnet wird, sind im User-Koordinatensystem im allgemeinen Gleitkomma-Zahlen zu bevorzugen. Die Umrechnung selbst kann mit den folgenden vier Funktionen implementiert werden:

In Delphi:
  • function userx (pbx: Integer): Double;
  • function usery (pby: Integer): Double;
  • function paintx (ux: Double): Integer;
  • function painty (uy: Double): Integer;
In Java:
  • function double userx (int px)
  • function double usery (int py)
  • function int paintx (double ux)
  • function int painty (double uy)

Wenn man diese Transfer-Funktionen zur Verfügung hat, kann man jederzeit im Programm User-Koordinaten in Painbox-Koordinaten umrechnen und umgekehrt. Damit können alle internen Rechnungen in User-Koordinaten (also den dem Problem angepaßten Koordinaten!) ausgeführt werden; für den Aufruf von Grafikbefehlen werden dann die berechneten Werte durch Aufrufe von "paintx" und "painty" in Paintbox-Koordinaten-Werte umgewandelt, die dann an die MoveTo und LineTo übergeben werden.


  1. Noch ein Funktionenplotter:

    Programme zur Darstellung von Funktions-Schaubildern gehören offenbar zu den obligatorischen Übungen aller angehenden Programmierer: anders ist die Vielzahl der verfügbaren Programme dieser Art kaum zu erklären. Nun sollen auch Sie einen kleinen Funktionenplotter erstellen. Wir beginnen mit einer ziemlich einfachen Variante, steigern die Leistungsfähigkeit des Programms aber im Verlauf der folgenden Aufgaben ganz erheblich.

    Zu Beginn verzichten wir erst mal auf eine Funktionstermeingabe; die darzustellende Funktion wird im Programm "festverdrahtet", und zwar als Funktion des Namens "f". Eine mögliche Implementierung für die Zeit der Entwicklung könnte wie folgt aussehen:

    In Delphi:
       function f(x: Double): Double;
         begin
         Result := 3*sin(x);
         end;
    Die Zeichenaktion soll durch einen Klick auf einen Knopf "Zeichnen" ausgelöst werden. Setzen Sie den Knopf in eine TPanel-Komponente, deren Align-Eigenschaft auf "alTop" gesetzt wird. Die Zeichnung selbst soll in einer TPaintBox-Komponente erstellt werden, deren Align auf "alClient" gesetzt wird, um automatische Skalierbarkeit des Formulars zu erhalten.

    Um einen weißen Hintergrund zu bekommen, genügt es leider nicht, die Color-Eigenschaft der PaintBox-Komponente auf clWhite zu setzen, da diese Komponente zunächst transparent ist. Daher müssen Sie die Color-Eigenschaft des (darunterliegenden!) Formulars auf clWhite setzen.
    In Java:
       public double f(x: Double) {
         return 3*sin(x);
       }

    Die Zeichenaktion soll durch einen Klick auf einen Knopf "Zeichnen" ausgelöst werden. Setzen Sie den Knopf in eine Panel-Komponente, der Sie im Objekt-Inspektor die Höhe 50 (Pixel) zuweisen und sie dann über die gesammte Fensterbreite horizontal aufziehen. Die Zeichnung selbst soll in einer Canvas-Komponente erstellt werden, die den restlichen freien Platz des Formulars belegt.

    Um einen weißen Hintergrund zu bekommen, genügt es, die Background-Eigenschaft der Canvas-Komponente auf WHITE zu setzen.

    Nach diesen vorbereitenden Schritten, die lediglich der Erstellung der Oberfläche dienten, wenden wir uns den "inneren Werten" unseres Programms zu. Es sind die folgenden Aufgaben zu erledigen:


    1. Die Funktionen für die Umrechnung zwischen dem User-Koordinatensystem und dem PaintBox-Koordinatensystem müssen erstellt werden:

    Das Paintbox-Canvas-Koordinatensystem rechnet in Integer-Werten (Pixeln!) und hat seinen Ursprung in der linken oberen Ecke; x-Werte nehmen nach rechts zu, y-Werte nach unten. Das User-Koordinatensystem rechnet in "logischen Zentimetern", die durch Real-Zahlen (z.B. Double) dargestellt werden; x-Werte nehmen nach rechts zu, y-Werte nach oben (wie üblich).

    Der Zusammenhang zwischen den beiden Koordinatensystemen ist durch die drei Variablen x0, y0 und ppcm vollständig festgelegt:

    • die Integer-Variablen x0 und y0 geben den Ort des User-Koordinatensystem-Ursprungs im Paintbox-Koordinaten-System an, und
    • die Double-Variable ppcm ( = "Pixel per Zentimeter"!) regelt die Umrechnung der Einheiten.

    Es ist für die folgenden Überlegungen wichtig, dass Sie die Bedeutung dieser Variablen vollständig verstanden haben. Verstanden hat man einen Sachverhalt dann, wenn man ihn einem Anderen, der ihn noch nicht verstanden hat, so erklären kann, dass dieser ihn dann auch verstanden hat (und ihn erklären kann). Am besten klären Sie den Zusammenhang zwischen den beiden Koordinatensystemen durch eine saubere Zeichnung, in der Sie alles, was zum Paintbox-Koordinatensystem gehört, in schwarzer Farbe einzeichnen, und alles, was zum User-Koordinatensystem gehört, in rot. Beachten Sie, dass ein beliebiger Punkt der Zeichenfläche damit durch zwei verschiedene Koordinatenpaare beschrieben wird!

    In Delphi deklarieren Sie nun die Variablen x0, y0 und ppcm im "private"-Abschnitt der Formular-Deklaration. Bevor Sie nun die vier oben angegebenen Umrechnungsfunktionen implementieren können, müssen diese drei Variablen mit sinnvollen Werten belegt werden. Dies sollten Sie sinnvollerweise gleich beim Programmstart in der OnCreate-Methode des Formulars erledigen:
       x0   := PaintBox1.Width div 2;
       y0   := PaintBox1.Heigth div 2;
       ppcm := 40.0;
    
    Damit wird der Ursprung des User-Koordinatensystems in die Mitte des Zeichenbereichs geschoben; außerdem wird festgelegt, dass die Einheitsstrecke 40 Pixel lang ist.
    In Java deklarieren Sie nun die Variablen x0, y0 und ppcm als "private" Variablen des Formulars. Bevor Sie nun die vier oben angegebenen Umrechnungsfunktionen implementieren können, müssen diese drei Variablen mit sinnvollen Werten belegt werden. Dies sollten Sie sinnvollerweise gleich beim Programmstart im Konstruktor des Formulars erledigen. Fügen Sie dazu am Ende des Konstruktor-Quelltextes die folgenden Anweisungen hinzu:
       x0   = canvas1.getWidth() / 2;
       y0   = canvas1.getHeigth() / 2;
       ppcm = 40.0;
    
    Damit wird der Ursprung des User-Koordinatensystems in die Mitte des Zeichenbereichs geschoben; außerdem wird festgelegt, dass die Einheitsstrecke 40 Pixel lang ist.

    Schreiben Sie nun die oben angegebenen vier Funktionen zur Umrechnung der Koordinaten zwischen den beiden Koordinatensystemen. Dabei hilft ihnen die zuvor angefertigte Zeichnung, mit deren Hilfe Sie den mathematischen Zusamenhang zwischen den Paintbox-Koordinaten und den User-Koordinaten eines Punktes konstruieren können.

    Für die praktische Arbeit ist es vorteilhaft, wenn wir noch vier weitere Variablen vereinbaren, die beschreiben, welcher Bereich des User-Koordinatensystems im Zeichenbereich dargestellt wird.

    Deklarieren Sie in Delphi entsprechende Double-Variablen xmin, xmax, ymin und ymax im "private"-Abschnitt der Formular-Deklaration, und setzen Sie sie in der OnCreate-Methode auf die korrekten Werte:
       xmin := userx(0);
       xmax := userx(Paintbox1.Width);
       ymin := usery(Paintbox1.Height);
       ymax := usery(0);
    
    Deklarieren Sie in Java entsprechende double-Variablen xmin, xmax, ymin und ymax als "private" Variablen des Formulars, und setzen Sie sie in im Formular-Konstruktor direkt nach der Initialisierung von x0, y0 und ppcm auf die korrekten Werte:
       xmin = userx(0);
       xmax = userx(canvas1.getWidth());
       ymin = usery(canvas1.getHeight());
       ymax = usery(0);
    


    2. Die Koordinatenachsen und ihre Beschriftung müssen gezeichnet werden:

    Dies kann zunächst in der OnClick-Prozedur des Knopfes geschehen. Geben Sie unter Zuhilfenahme der Koordinaten-Umrechnungsfunktionen und der Bereichsgrenzen das Koordinatensystem auf dem Zeichenbereich aus. Zum Zeichnen der Achsen gehen Sie wie folgt vor:

    In Delphi sind die Zeichenbefehle als Methoden von Paintbox.Canvas implementiert. Um Schreibarbeit zu sparen, können Sie den Canvas in einer lokalen Variablen c zwischenspeichern:
      procedure TForm1.Button1Click(Sender: TObject);
        var c : TCanvas;
        begin
        c := Paintbox1.Canvas;
        c.MoveTo(paintx(xmin), painty(0));
        c.LineTo(paintx(xmax), painty(0));
        c.MoveTo(paintx(0), painty(ymin));
        c.LineTo(paintx(0), painty(ymax));
        end;
    
    In Java sind die eigentlichen Zeichen-Befehle in einem Graphics-Objekt versteckt, das man sich erst vom Canvas-Objekt geben lassen muss:
      public void button1_ActionPerformed(ActionEvent evt) {
        Graphics g = canvas1.getGraphics();
        g.drawLine(paintx(xmin), painty(0), paintx(xmax), painty(0));
        g.drawLine(paintx(0), painty(ymin), paintx(0), painty(ymax));
      }
    

    Ergänzen Sie dies durch die Ausgabe von Skalierungsstrichen an den beiden Achsen. Machen Sie sich klar, dass ein 0,4 L.E. langer Skalierungsstrich bei (x = -3) durch den folgenden Code ausgegeben wird:

    Für Delphi:
       c.MoveTo(paintx(-3), painty( 0.2));
       c.LineTo(paintx(-3), painty(-0.2));
    
    Erzeugen Sie in einer Schleife, die von Round(xmin) bis Round(xmax) läuft, alle nötigen Skalierungsstriche auf der x-Achse. Erzeugen Sie danach analog die Skalierung der y-Achse.

    Richtige Profis schreiben dann noch die Zahlen an die Skalierungsstriche. Benutzen Sie dazu die Canvas.TextOut()-Methode! Details dazu finden Sie in der Online-Hilfe zu Delphi.
    Für Java:
       g.drawLine(paintx(-3), painty( 0.2), paintx(-3), painty(-0.2));
    
    Erzeugen Sie in einer Schleife, die von ((int) xmin) bis ((int) xmax) läuft, alle nötigen Skalierungsstriche auf der x-Achse. Erzeugen Sie danach analog die Skalierung der y-Achse.

    Richtige Profis schreiben dann noch die Zahlen an die Skalierungsstriche. Benutzen Sie dazu die Graphics.drawString()-Methode! Details dazu finden Sie in der Online-Hilfe zu Java.

    Und wenn Sie's ganz besonders schön machen wollen, können Sie noch alle Gitterpunkte mit ganzzahligen Koordinaten mit einem Punkt (oder einem kleinen Kreuz) belegen. Diese "Orientierungspünktchen" helfen später beim Ablesen von Funktionswerten aus dem Schaubild!



    3. Das Funktionsschaubild muss ausgegeben werden:

    Dies ist nach den obigen Anstrengungen nun eine nicht gar so schwere Übung. Ergänzen Sie Ihre Click-Prozedur durch eine Schleife, die das Schaubild der Funktion f ins schon vorhandene Achsenkreuz einzeichnet:

    Deklarieren Sie zunächst zwei lokale Variablen x und y, sowie eine Schrittweite dx, alles als Double. Arbeiten Sie sich dann von x = xmin aus in kleinen Schritten der Weite dx bis zu x >= xmax vor; berechnen Sie für jedes x das zugehörige y := f(x) und zeichnen Sie mit einem LineTo-Befehl stückchenweise das Schaubild.
    (Achtung! Vor dem Start der Schleife muss ein MoveTo-Befehl den Grafik-Cursor an die "richtige" Stelle schieben!)
    Deklarieren Sie zunächst zwei lokale Variablen x und y, zwei weitere namens x_a und y_a, in denen die "alten" Werte aufgehoben werden, sowie eine Schrittweite dx, alles als double. Arbeiten Sie sich dann von x = xmin aus in kleinen Schritten der Weite dx bis zu x >= xmax vor; berechnen Sie für jedes x das zugehörige y = f(x), und zeichnen Sie mit einem drawLine()-Befehl stückchenweise das Schaubild.
    (Achtung! Da jeder drawLine()-Befehl einen Start- und einen Endpunkt braucht, müssen Sie sich genau überlegen, wie sie hier vorgehen wollen!)

    Ein weiteres Problem ist die Wahl der Schrittweite dx. Machen Sie sich klar, dass der Wert 1/ppcm eine sinnvolle Wahl für dx ist. Warum?

    [Lösungsvorschlag]




  2. Und nun die Luxusversion!

    Das Programm aus der vorigen Aufgabe hat mehrere Nachteile, die wir nun einen nach dem anderen beheben werden.


    1. Eine kosmetische Korrektur:

    In der Klick-Prozedur des Knopfes werden eigentlich zwei verschiedene Aufgaben erledigt, die inhaltlich deutlich voneinander zu trennen sind:
    1. Es wird das Koordinatensystem gezeichnet.
    2. Es wird das Schaubild der verlangten Funktion gezeichnet.
    Obwohl das Programm natürlich auch im bisherigen Zustand funktioniert, ist es für kommende Wartungsarbeiten günstiger, jede dieser Aufgaben in einer eigenen Prozedur zu erledigen und in der Klick-Prozedur dann diese einzelnen Prozeduren aufzurufen. Deklarieren und implementieren Sie also die beiden Prozeduren "DrawCoordSys" und "DrawFunction".

    Verlagern Sie ebenso den kompletten Inhalt der OnCreate-Methode in eine eigene Prozedur "InitScale", die Sie dann in der OnCreate-Methode aufrufen. Dies scheint im Augenblick noch nicht sehr sinnvoll zu sein; es wird sich aber im Folgenden als ein Vorteil erweisen, wenn die Initialisierung der (formular-)globalen Variablen von jeder anderen Stelle unseres Programms auf einfache Art und Weise aufgerufen werden kann. (Warum könnten Sie eigentlich die OnCreate-Methode nicht so ohne weiteres direkt aufrufen?)


    2. Warum verschwindet unsere Zeichnung gelegentlich?

    Wenn wir das Programm laufen lassen und das Funktionsschaubild anzeigen lassen, dann ist diese Anzeige merkwürdig flüchtig: wenn ein anderes Fenster (z.B. ein NotePad-Fenster) unsere Paintbox vorübergehend überdeckt hatte, dann verschwindet genau der Teil unserer Grafik, der zwischenzeitlich vom anderen Fenster verdeckt wurde. Überzeugen Sie sich davon!

    Wir verstehen dieses unschöne (und von normalen Windows-Programmen nicht gewohnte) Verhalten, wenn wir uns klar machen, wann in unserem Programm eigentlich das Schaubild gezeichnet wird: nämlich genau dann, wenn wir auf den Knopf klicken. Offenbar genügt das aber nicht. Das Schaubild sollte auch dann neu gezeichnet werden, wenn unser Fenster wieder hinter einem anderen Fenster hervorkommt....

    Einem aufmerksamen Beobachter könnte auffallen, dass der Rahmen unseres Fensters ja nicht verschwunden bleibt, wenn wir das Notepad-Fenster wieder entfernen. Dieser Rahmen wird offenbar von Windows automatisch immer wieder restauriert, wenn es nötig ist. Und genau in diese Restaurierungs-Prozedur können wir uns einklinken, indem wir unsere Grafikausgaben zusätzlich in der OnPaint-Methode der Paintbox machen lassen. Erzeugen Sie diese OnPaint-Methode, indem Sie
    1. die Paintbox fokussieren;
    2. im Objektinspektor auf die Seite "Ereignisse" wechseln und
    3. in das leere Feld neben dem Eintrag "OnPaint" einen Doppelklick machen.
    Rufen Sie dann in dem automatisch erzeugten Prozedurrumpf die Prozeduren "DrawCoordSys" und "DrawFunction" auf.

    Wenn Sie das Programm nun laufen lassen, wird das Schaubild schon sofort nach dem Programmstart angezeigt: unser Knopf ist derzeit offenbar überflüssig! (Lassen Sie ihn trotzdem am Leben.) Die OnPaint-Methode wird offenbar immer dann automatisch (von Windows) aufgerufen, wenn die Paintbox neu gezeichnet werden muss, oder - um in der Windows-Terminologie zu sprechen - "wenn ein OnPaint-Ereignis eintritt".

    Dies ist schon das zweite "Ereignis", das wir in unserem Programm ausnutzen. Das erste ist das OnCreate-Ereignis, welches gleich beim Programmstart eintritt und zum Aufruf der OnCreate-Methode (des Formulars) führt: dort haben wir die Variablen initialisiert!


    3. Flexibilität ist (fast) alles: ein Fenster wie Gummi!

    Durch unsere vorausschauende Planung beim Aufbau des Formulars und den klugen Einsatz der Align-Eigenschaften von Panel- und Paintbox-Komponente ist gewährleistet, dass der Benutzer die Fenstergröße zur Laufzeit ändern kann, wobei die Panel-Komponente mit den Steuerelementen (derzeit nur unser arbeitsloser Knopf!) immer am oberen Fensterrand verbleibt und die Paintbox den restlichen Platz ausfüllt. Leider reagiert unser Programm noch nicht korrekt, was das Schaubild angeht!

    Jede Größenveränderung des Fensters löst ein OnResize-Ereignis aus, das die zugehörige OnResize-Methode des Formulars aufruft. Dies ist die Stelle, wo wir festlegen können, was direkt nach einer Größenänderung des Fensters geschehen soll.

    Zur Erzeugung der OnResize-Methode wählen Sie aus der DropDown-Liste des Objektinspektors das Formular aus (Eintrag "Form1: TForm1"). Gehen Sie dann auf die Seite "Ereignisse" und erzeugen Sie durch einen Doppelklick recht neben den Eintrag "OnResize" die OnResize-Methode. Fügen Sie in den automatisch erzeugten Rumpf der Mathode den Aufruf der Prozedur "InitScale" ein. Dadurch werden nach jeder Änderung der Fenstergröße die (formular-)globalen Variablen neu gesetzt, welche die Größe und Lage des Zeichenbereichs regeln. Nun ist unser Fenster ohne Einschränkungen skalierbar.


    4. Nicht immer nur Sinus.....

    Die unangenehmste Eigenschaft unseres Programms ist es wohl, dass die darzustellende Funktion stets zur Designzeit, also vor dem Kompilieren des Programms eingegeben werden muss. Viel besser wäre es, wenn Sie den Funktionsterm zur Laufzeit eingegeben könnten. Bevor wir dieses Problem lösen (lassen!), sollten wir uns darüber klar werden, was da eigentlich zu tun ist:

    Wenn wir einen Funktionsterm eingeben, dann ist dies eine Folge von Zeichen, die eine gewisse festgelegte Bedeutung haben. So bedeutet z.B. das Zeichen "x", dass an seiner Stelle der aktuelle Wert der Variablen x zu nehmen ist, und "3*x^2" bedeutet, dass dieses x zu quadrieren und das Ergebnis mit 3 zu multiplizieren ist. Beachten Sie, dass die Reihenfolge der Rechenschritte der üblichen Operatoren-Hierarchie der Mathematik gehorchen muss, und nicht der Reihenfolge, in der die entsprechenden Zeichen im eingegebenen String vorkommen!

    Die Aufgabe, einen Funktionswert y an einer vorgegebenen Stelle x zu berechnen, besteht also darin, die eingegebene Funktionsterm-Zeichenkette nach den Regeln der Termauswertung zu interpretieren. Die Entwicklung eines entsprechenden Programms füllt locker mehrere Monate eines fortgeschrittenen Grundkurses Informatik....

    Glücklicherweise bekommen wir mit der TermEdit-Komponente eine "schlüsselfertige" Lösung geliefert: in das TermEdit-Feld wird ein Term eingegeben, der intern interpretiert und ausgewertet wird. Funktionswerte der eingegebenen Funktion kann der Programmierer ermitteln, indem er der Funktion "f" der TermEdit-Komponente den gewünschten x-Wert (als Double) übergibt; das zurückgelieferte Funktionsergebnis ist dann der zugehörige y-Wert.

    Setzen Sie in das Panel ein TermEdit-Komponente. Löschen Sie dann Deklaration und Implementierung der bisherigen "festverdrahteten" Funktion f, und benutzen Sie stattdessen die Funktion "TermEdit1.f". Geben Sie bitte schon zur Designzeit einen gültigen Funktionsterm in das "Text"-Feld der TermEdit-Komponente ein, damit Sie beim Programmstart keine Initialisierungsprobleme bekommen.


    5. Der letzte Schliff

    Wenn wir nun zur Laufzeit des Programms den Funktionsterm verändern und danach auf den Knopf klicken, dann wird das zum neuen Term gehörende Schaubild zusätzlich zum schon vorhandenen in das Koordinatensystem eingezeichnet. Das ist nicht schön, kann aber leicht durch eine Überarbeitung der Click-Prozedur behoben werden:

    Was soll eigentlich beim Klick auf den Knopf passieren? Die Paintbox sollte gelöscht und komplett neu gezeichnet werden! Die entspricht einem Aufruf der OnPaint-Methode der Paintbox. Eigentlich müssten wir nur Windows überreden, die Paintbox neu zu zeichnen. Dies können wir tatsächlich tun, und zwar indem wir Windows mitteilen, dass das Fenster ungültig geworden ist: der entsprechende Befehl heißt "Invalidate". Schreiben Sie diesen einen Befehl in die Klick-Prozedur des Knopfes und löschen Sie alle anderen Befehle heraus. Jetzt verhält sich das Programm erwartungsgemäß.

    [Lösungsvorschlag]



  3. The show must go on...

    Wenn Sie das Programm nun aber mit verschiedenen Funktionstermen testen, werden Sie feststellen, dass da immer noch einiges zu tun bleibt. Formulieren Sie einige Kritikpunkte, und versuchen Sie, Lösungen zu implementieren!





Zum vorigen Kapitel Zum Inhaltsverzeichnis Zum nächsten Kapitel