LAZ 9. Wir malen...

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Wir arbeiten mit grafischen Systemen, also können wir dies auch nutzen.
    In diesem Exkurs geht es um Zeichenflächen und die Behandlung von Bitmap Objekten
    Lazarus bietet uns alles, um grafisch zu arbeiten.




    Um Bilder darzustellen, muss man dazu nur die TImage Komponente (Additional) verwenden. Die Eigenschaft "Picture" lässt uns direkt Bilder öffnen, welche auf der Form gezeigt werden.
    Das alleine wäre aber langweilig. Probiere es aus, größere Schwierigkeiten sind dabei nicht zu erwarten.

    Wir werden jetzt aber die Manipulation von Zeichenflächen verwenden.
    Warum verwende ich den Begriff "Zeichenfläche" nun schon zum wiederholten Mal?
    Ganz einfach. Das englische Wort für Zeichenfläche ist CANVAS

    Dieses Wort wird dich immer verfolgen, wenn irgend etwas nach Grafik aussieht in Lazarus.

    In einem der vorherigen Einführungen in Lazarus habe ich beschrieben, das es um Objekte geht; objektorientierte Programmierung.
    Diese Objekte sind alle von gewissen Grundtypen von Objekten abgeleitet.

    TCanvas ist solch ein rudimentärer Typ. Alle für uns sichtbaren Objekte stammen von TCanvas ab. Gemeinsam ist: Sie haben eine Zeichenfläche!
    Jeder Button, jede Checkbox, ja sogar unser Hauptfenster Form1 aus vorherigen Beispielen, hat eine Canvas.

    Das würde ja bedeuten, dass man einfach so auf dem Fenster malen kann?

    JA! So ist es... und dies werden wir jetzt erarbeiten.

    Starte ein neues Projekt in Lazarus (Anwendung)
    Erzeuge zwei Button, ein Spinedit, eine Colorbox (Additional) und 4 Label.
    Das sollte nach wenigen Anpassungen in etwa so aussehen
    "(0, 0)" ist ebenfalls ein Label, wobei ich hier über die Eigenschaft "Font" die Schriftgröße verändert habe.

    Ziel ist, bei gedrückter linker Maustaste auf der Fensterfläche von Form1 malen zu können.
    Wir erinnern uns: Praktisch fast alles ist EREIGNIS-GESTEUERT!
    Beim Malen bewegt der Anwender die Maus und drückt die Maustaste. Das sind die Ereignisse, welche hier interessant sind.
    Da wir auf Form1 malen wollen, sind es im speziellen die Ereignisse, welche Form1 auslöst.
    Schau im Objektinspektor unter From1 Ereignisse nach.
    Du findest ein Ereignis onMouseMove. Ideal für uns! "Wenn der Anwender die Maus bewegt..."

    Klick also dieses "Event" doppelt und erzeuge so die Procedure dafür.
    Wir legen gleich richtig los, hier ist die Procedure, mit allem, was hinein gehört.
    Wir besprechen direkt im Anschluss die Details!


    LAZARUS-Quellcode

    1. procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    2. begin
    3. label3.caption := '(' + inttostr(x) + ', ' + inttostr(y) + ')';
    4. if (shift = [ssLeft]) and ( y > 50 ) and (x <= Form1.width - SpinEdit1.Value) then
    5. begin
    6. Form1.Canvas.brush.Color:=ColorBox1.Selected;
    7. Form1.Canvas.FillRect(x, y, x+SpinEdit1.Value, y+SpinEdit1.Value);
    8. end;
    9. end;


    Der Procedure Rumpf ist soweit nichts Neues, außer, dass wir drei Werte übergeben bekommen bei Aufruf dieser Procedure.
    Shift, X und Y
    Shift ist eine Aufzählung von Eigenschaften der Maus-Button. X und Y sind die Koordinaten des Mauszeiger auf unserem Fenster Form1.

    Die Zeile label3.caption := '(' + inttostr(x) + ', ' + inttostr(y) + ')'; ist zur Anzeige der Maus-Koordinaten eingebaut und bewirkt nichts, außer auf Label3 die Koordinaten darzustellen.
    Wie du erkennst, werden Strings über das Pluszeichen ( + ) verkettet bzw aneinander gehängt. Im Gegensatz zu Bascom ist es kein doppeltes Anführungszeichen, sondern ein einfaches Anführungszeichen, welches die Zeichen eines String einschließt. Kleinigkeiten, aber wir sollten das kurz erwähnt haben.

    Diese Zeile
    if (shift = [ssLeft]) and ( y > 50 ) and (x <= Form1.width - SpinEdit1.Value) then
    müssen wir uns genauer anschauen...

    Sie besteht aus drei geklammerten Ausdrücken, welche alle erfüllt sein müssen.
    1) (shift = [ssLeft])
    hier muss die Bedingung erfüllt sein, dass die in Shift übergebene Maustaste im "Set" enthalten ist. Das "Set" ist eine Aufzählung von möglichen Elementen.
    Als einzig zulässig ist hier ssLEft enthalten. Die linke Maustaste muss gedrückt sein...

    2) ( y > 50 )
    Der Wert von Y muss größer 50 sein. Dies sind 50 Pixel vom oberen Rand unserer Form1 entfernt. Würden wir dies nicht als BEdingung definieren, könnte der Anwender unseres Programms im Bereich der Button malen und das verhindern wir dadurch.

    3) (x <= Form1.width - SpinEdit1.Value)
    Hierdurch wird ein Überschreiben des rechten Rand unserer Form1 verhindert. Könnte der Anwender bis zum letzten Punkt am rechten Rand bei einer Stiftweite von 10 Punkten malen, würden wir 9 Punkte über den rechten Rand malen. Aus diesem Grund reduzieren wir den Zeichenbereich um die Stiftstärke.


    Wenn vorstehende Bedingungen erfüllt sind, werden die zwei Zeilen zwischen begin und end ausgeführt.

    1) Form1.Canvas.brush.Color:=ColorBox1.Selected;
    Hier sehen wir das erste Mal in unserem Projekt das Wort Canvas. Es hängt per Punkt hinter dem Namen Form1.
    Dies bedeutet, dass Canavas eine Eigenschaft von Form1 ist! Unsere Form1 hat also definitiv eine Zeichenfläche a_64_3a718cae

    ...aber hinter Canvas geht es weiter... .brush : "brush" bezeichnet die Füllung eines Objektes
    ...und es geht noch weiter... .color : "color" bezeichnet die Farbe

    im Ganzen gesehen: Form1.Canvas.brush.Color --> "Form1 seine Zeichenfläche die Pinselfarbe für Füllung" so ungefähr kann man das übersetzen a_48_7237538e
    Ok, wir wissen nun, worum es sich handelt und was wird dem zugewiesen über ":=" ?
    Es ist ColorBox1.Selected Oh man, noch so ein wirres "Ding"... a_56_df238249
    Die Colorbox ist im Grunde eine "Auswahlbox", wie man sie kennt, jedoch sind die Werte, welche zur Auswahl stehen, FARBEN des Systems. Das ist "obercool"! Wir können als Anwender eine Farbe in einem Objekt (Colorbox) auswählen und im Programmcode verwenden wir einfach die Eigenschaft "selected" um an die ausgewählte Farbe zu kommen.

    Jetzt die Funktion der gesamten Zeile auf Deutsch: Weise der Füllfarbe der Zeichenfläche von Form1 die ausgewählte Farbe der Colorbox zu. That's it! nicht mehr und nicht weniger passiert in dieser Zeile. a_167_7bbcf6ac
    ...viel geschrieben, wenig auf der Zeichenfläche gemalt, das ändern wir aber mit der nächsten, alles entscheidenden Zeile!

    2) Form1.Canvas.FillRect(x, y, x+SpinEdit1.Value, y+SpinEdit1.Value);
    ist nun die entscheidende Funktion, damit wir endlich etwas sehen. Eine Funktion vom Canvas Objekt unser Form1 ist FillRect.
    FillRect füllt ein rechteckigen Bereich auf der Zeichenfläche mit der ZUVOR ANGEGEBENEN Füllfarbe! (...wir sind clever, hä? :thumbup: haben wir schon erledigt...)
    Dazu werden zwei x,y Punkte als Koordinaten für das Rechteck übergeben. Die Übergabe erfolgt in unserem Code mit zusätzlicher Berechnung wegen der Strichbreite, mit der wir zeichnen. Diese kann man in Spinedit1 festlegen.

    Jetzt kannst du das Projekt kompilieren, eine Farbe und die Stiftbreite auswählen und die ganze Form1 bunt anmalen a_57_04ef5ee8

    Als nächsten Schritt bauen wir eine Löschfunktion ein, denn nicht jeder ist ein Picaso rolling:
    Für den Button1 eine onClick Procedure erzeugen.

    LAZARUS-Quellcode

    1. procedure TForm1.Button1Click(Sender: TObject);
    2. begin
    3. Form1.Canvas.brush.Color:=clwhite;
    4. Form1.Canvas.FillRect(0,50,form1.width,form1.height);
    5. end;

    Die erste Zeile ist bekannt. Hier wird die Füllfarbe zugewiesen --> weiß soll es sein.
    Die zweite Zeile bietet auch keine Geheimnisse mehr für uns! Diesmal wird in den Koordinaten die ganze Ausdehnung vom Fenster Form1 angegeben und mit weiß gefüllt.

    Bleibt ein letzter Punkt: Wir haben etwas wertvolles gemalt und wollen das der Nachwelt erhalten.
    Dazu für Button2 eine onClick Procedure erzeugen

    LAZARUS-Quellcode

    1. procedure TForm1.Button2Click(Sender: TObject);
    2. var
    3. Mein_Bild : TBitmap;
    4. begin
    5. Mein_Bild := TBitmap.Create;
    6. Mein_Bild.Width:=form1.Width;
    7. Mein_Bild.Height:=form1.Height-50;
    8. Mein_Bild.Canvas.CopyRect(Rect(0,0,form1.Width,form1.Height-50), form1.Canvas, Rect(0,50,form1.width, form1.height));
    9. Mein_Bild.SaveToFile( extractfilepath(application.exename) + 'Mein_Bild.bmp');
    10. Mein_Bild.free;
    11. end;
    Alles anzeigen
    Aus dem vorherigen Kapitel "INIFILES" kennst du bereits die Technik, Objekte im Quelltext erzeugen zu können. Diesmal ist es kein TINIFILE sondern eine TBITMAP.
    Über WIDTH und HEIGHT legen wir die Größe der Bitmap im Speicher fest.
    Durch Canvas.copyrect kopieren wir uns, unter Angabe der jeweiligen Koordinaten für den Bereich, welcher kopiert wird, unser Bild von Form1.Canvas.
    Wir haben jetzt also eine Kopie unseres Bildes im Speicher des Rechners!
    Der große Vorteil einer TBitmap ist, dass sie die Eigenschaft SaveToFile besitzt! Das kann unsere Form1.Canvas nicht!
    Letzter Schritt ist also, die Schreibroutine für unsere Bitmap aufzurufen:

    Mein_Bild.SaveToFile( extractfilepath(application.exename) + 'Mein_Bild.bmp');
    Extractfilepath ist aus vorigem Kapitel bereits bekannt.


    Jetzt könntest du das Projekt kompilieren (grüner Pfeil)... wie du eventuell gemerkt hast, wird beim Start des Kompilierens automatisch alles gespeichert
    Ich habe dir immer zwischendrin den Tipp gegeben, dein Projekt zu speichern. Dies passiert auch automatisch beim kompilieren... nur mal so am Rande


    Ich hoffe, die kleine Exkursion in den Bereich der Farben und Formen hat dir gefallen.




    Download ganzes Projekt...

    515 mal gelesen