Delphi

LOGBuch Projekt MiniPaint

Wir haben in den letzten Wochen das Projekt "MiniPaint" bearbeitet und den Arbeitsfortschritt in einem LOGBuch festgehalten. Im Anhang befinden sich 4 LOGBücher und die jeweiligen Lösungen dazu.

LOGBuch von AlexanderM und ThimoR

26.10.2007 - Planung/Design
Wir fangen mit dem Projekt MiniPaint an.

Als erstes haben wir uns überlegt, welche Funktionen wir in unser MiniPaint einbauen. Als nächstes haben wir dann ein Layout entworfen und alles weitere (Buttons etc.) zum Programmieren vorbereitet.

Das Layout wird ungefähr so aussehen:

30.10.2007 - Code wird geschrieben
Wir haben mit dem Programmieren begonnen.

Verfügbare Eigenschaften:

  • Freihand zeichnen
  • Linien zeichnen
  • Ellipse zeichnen
  • Stiftdicke einstellen
  • Stiftfarbe einstellen
  • Werkzeugleiste öffnen, schließen und verschieben
  • Programm beenden
  • Zeichnung löschen
09.11.2007 - Code für Ellipse...leider Probleme
Wir haben die Transparenz von der Ellipse Auswahlfähig gemacht. Durch Container können wir die zugehörigen SpeedButtons Ein- bzw. Ausblenden.

Leider haben wir Probleme die Transparenz richtig anzuzeigen bzw. zu zeichnen.

Die Farben werden nicht richtig wie erwünscht gezeichnet.

13.11.2007 - Paint wurde erweitert
Wir haben die Möglichkeit Kreise und Rechtecke zu zeichnen, Problem mit der Transperenz wurde gelöst.


16.11.2007 - Paint bekommt ein Menü

Wir haben nun angefangen (Betonung auf "angefangen") ein Menü für unser Paint.

Zur Zeit funktioniert:

  • Neu (das Bild wird gelöscht, also wie der Lösche-Button es auch macht)
  • Beenden (das Programm wird beendet, also wie der Beenden-Button)

In Zukunft kommt rein:

  • Speichern
  • Speicher als...
  • Laden
20.11.2007 - mit Speichern und Farbwahl erweitert

Nun wurden versucht das Speichern des Bildes zu integrieren.
Dies ist auch mit einer speziellen Methode möglich, aber diese ist nur für ein TImage-Objekt verfügbar Deshalb wurde, statt der Form, ein Bild eingeführt, das als Leinwand (Canvas) dient.
Das Speichern funktionierte auch, aber man muss den Dateinamen und die Dateierweiterung im Quelltext angeben. Das kam nicht in Frage!
MiniPaint ist interaktiv. Es soll mit dem Benutzer kommunizieren. Also haben wir ein SaveDialog implementiert mit dem es allerdings noch etwas Probleme gibt.

Außerdem wurde noch die Farbwahl verbessert. Es ist nun möglich durch eine Farbtabelle eine benutzerdefinierte farbe zu benutzen.

Das Programm kommt langsam ans Finale ran.
Was noch rein kommen soll sind:

  • Radiergummi (Wieso haben wir's noch nicht drin?)
  • optische Verschönerungen (wie z.B. die Vorschau der ausgewählten Farbe, Grafiken einbetten, usw.)

Einstieg in Canvas

In dieser Woche haben wir uns die grundlegenden Canvas-Methoden angesehen.

Zum Einstieg haben wir zuallererst eine einfache Zeichnung auf einem Din A4 Blatt erstellt. Die Eckpunkte dieses Blattes haben wir mit den Koordinaten (0,0),(700,0),(0,500),(700,500) beschriftet, welche später am Computer für Pixel stehen.

Diese Zeichnung sollten wir dann mit Delphi erstellen. Hierbei hat es sich als sinnvoll dargestellt, wenn man schon vorher auf dem Papier alle Eckpunkte innerhalb der Zeichnung mit Koordinaten versehen hatte, um ein Gefühl für die Proportionen zu bekommen. Falls die eigene Papierzeichnung sich nicht zur Darstellung eignete, konnte man stattdessen auch das "Haus vom Nikolaus" erstellen; wer wollte sogar mit Anbau.
Das Programm für die Zeichnung sollte so aussehen, dass die ganze Zeichnung beim Klick auf einen Button "Zeichnen" erstellt wird -> sodass sich also alle folgenden Methoden in diesem Button konzentrierten:

Canvas.pen.color :=clRed //Ändert die Farbe des Stift-Objekts Pen
Canvas.pen.width :=2 //Ändert die Strichstärke des Stift-Objekts Pen
Canvas.moveto (x,y) //Setzt die aktuelle Position auf die Koordinaten (x,y)
Canvas.lineto(x,y) //Zeichnet eine Linie von der aktuellen Position bis zum Punkt (x,y); (x,y) wird die neue aktuelle Position
Canvas.Rectangle(x1,y2,x1,y2) //Zeichnet ein Rechteck mit den gegenüberliegenden Eckpunkten P(x1,y2) und Q(x1,y2)
Canvas.Ellipse(x1,y1,x2,y2) //Zeichnet eine Ellipse innerhalb des imaginären Rechteck mit den Eckpunkten P(x1,y1) und Q(x2,y2); ist dieses ein Quadrat, wird ein Kreis gezeichnet.


Lampenspiele erstellen mit der random-Funktion, Prozeduren, Arrays und Variablen

Die Woche im Überblick:
Wir haben mit einem neuen Projekt begonnen: das Lampenspiel.
Ziel des Spiels ist es, alle Felder in einer Farbe zu bekommen.
Wir haben insgesamt 2 Versionen.

Version 1:
Man hat 7 Felder im Kreis angeordnet. Beim Klicken auf einem Feld wird die Farbe des Feldes und der umliegenden Felder umgekehrt.
Version 2: Man hat 4*4 Felder, also insgesamt 16 Felder. Beim Klicken auf einem Feld wird die Farbe des Feldes und die Felder mit der Position (relativ zum geklicktem Feld) -4, -1, +1 und +4 umgekehrt.
Beim Ausführen des Programms wird verständlich, was gemeint ist.

In dieser Woche gab es eine Menge an Theorie. Wir hatten einmal die random-Funktion und einen "Crash-Kurs" in Sachen Prozeduren, Arrays und Variablen.

Die random-Funktion:

Die random-Funktion ist vom Typ Integer (Zahlen, wie z.B. 0,1,2,...). Es werden "Zufallszahlen" aus gegeben, aber nicht irgendwelche. Man grenzt die Zahlen durch eine Zahl in der Klammer hinter dem random ein. Ein Beispiel: random(2). Die 2 bedeutet das die random 2 Möglichkeiten stellt, entweder gibt sie 0 oder 1 aus.

Wichtig ist das man die random-Funktion zuvor mit randomize; einleiten muss. Dies ist nur einmal am Anfang notwendig. So wird der Funktion gesagt, dass es den "Zufallsgenerator" einschalten soll.

Für unser kleines Programm mussten wir die random-Funktion in einer Bedingung einbauen. Beispiel:
if random(2) = 1
then .....
Die random-Funktion gibt ja 0 oder 1 aus, und wenn 1 ausgegeben wird ist diese Bedingung true. Es wird then ausgeführt.

Prozeduren:

Prozeduren werden mit procedure eingeleitet. Diese sind gefolgt vom Formulartyp, einem Punkt ("."), dem Namen der Methode und in Klammern die Parameter. Hinter der letzten Klammer muss ein Semikolon(";") gesetzt werden. In der neuen Zeile steht das begin, dass den Anfang der Anweisungen angibt, die ausgeführt werden sollen. Beendet werden Prozeduren mit einem end;. Unser Beispiel:
procedure TForm1.FarbeWechseln (LampenNr: Integer)

Die Prozedur muss auch im Kopf der Unit stehen, und zwar unter public, wo unsere eigenen Deklarationen eingefügt werden und das ganze Programm darauf Zugriff hat und unter implementation, wo unsere ganze Prozedur inklusiv Code steht.

Wenn man dies gemacht hat kann man dann beliebig oft auf diese Prozedur zugreifen und uns lästige Schreib- und Kopierarbeit sparen.

Das Array:

Ein Array ist ein Feld für einen Datentyp, indem man beliebig viele Daten speichern kann. Man kann sich ein Array wie einen Schrank mit Schubladen vorstellen. Man kann in jeder Schublade etwas abstellen.

Man deklariert Arrays unter var, wo der Typ einer Variable definiert wird.
Auch hier wieder ein Beispiel:
a: array [1..16] of TPanel;

Nun ist a ein Array mit 16 "Schubladen. In diesem Array dürfen nur Panelobjekte gespeichert werden, da wir dem Array den Datentyp TPanel zuweisen. Wichtig sind die Punkte innerhalb der eckigen Klammern. Es dürfen nur 2 sein, da sonst ein Fehler ausgelöst wird. Der Doppelpunkt(":") hinter dem a bedeutet "ist vom Typ".
Man könnte es also ungefähr so lesen:
a ist vom Typ array mit den Fächern 1 bis 16 in dem nur Panelobjekte gespeichert werden dürfen.

Man greift auf einem Fach im Array mit [Zahl] zu und weist es bei uns einem Panel durch ":=" zu. Unser Beispiel:
a[1] := Panel1;

Wie haben nun dem ersten Fach des Array ein Panelobjekt zugewiesen.

Zum besseren Verständnis stehen beide Lampenspiele im Anhang zur Verfügung.

Ich denke, dass damit die wichtigsten Sachen genannt worden sind, die in dieser theoriereichen Woche vorkam. Bei Fragen einfach Kommentar schreiben.

Alex M.


Ampelschaltung mit Panels

Inhalte der Woche:

 

In dieser Woche haben wir uns mit programmierten Ampel auseinandergesetzt. Am Dienstag, in unserer ersten Stunde haben es gegen Ende doch alle geschafft und wir hatten unsere erste Ampel, die man mit den 4 Buttons: "Rot", "Rot/Gelb", "Gelb" und "Grün" bedienen konnte.

Da wir natürlich alle zu faul sind alle 4 Buttons nacheinander zu drücken haben wir uns in der ersten Stunde der beiden Doppelstunden ein Programm ausgedacht mit dem wir mit dem einzigen Knopf "Schalten" unsere Ampel durchschalten konnten.

In der zweiten Stunde haben wir dann noch einen ein- und abschaltbaren Timer eingebaut, mit diesem wurde die Ampel in einem bestimmten Interval selbst umgeschaltet.

 

Neue Befehle:

Der wichtigste neuste Befehl dieser Woche war ganz sicher das altbekannte "Wenn ... dann ..." wie man es aus nahezu allen Programmierumgebungen kennt.
Wichtig hierbei sind die 3 Grundgerüste.

1. Einseitige Entscheidungen
if <Bedingung> then <Anweisung>


2. Zweiseitige Entscheidungen
if <Bedingung> then <Anweisung> else <Anweisung>


3. Mehrfache Entscheidungen
if <Bedingung> then <Anweisung> else if <Bedingung> then ...


Nicht ganz so wichtig, aber auch erwähnenswert ist die Verknüpfung "and" mit der man mehrere Bedingungen miteinander logisch verknüpfen konnte.

Schwierigkeiten:

Ab und wann gab es Schwierigkeiten, wie z.B. bei dem genauen Einsetzenvon Klammern, nahezu 50% hatte einen Fehler bei dem Aufschreiben der Bedingungen im Quelltext, da man diese einklammern musste.
Aber sonst hatten es doch alle geschafft zumindest ihre "Schaltampel" fertigzustellen.

Tobias


Inhalt abgleichen