• Keine Ergebnisse gefunden

Einführung in die objektbasierte Programmierung mit Delphi

N/A
N/A
Protected

Academic year: 2022

Aktie "Einführung in die objektbasierte Programmierung mit Delphi"

Copied!
29
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Einführung in die objektbasierte Programmierung mit Delphi

Klaus Becker

iMedia 2007

(2)

2

Orientierung

Der Einstieg in die Programmierung mit Delphi bereitet so mancherlei Schwierigkeiten. Auch einfachste Programme sind zunächst schwer zu durchschauen. Kompliziert ist insbesondere das Zusammenspiel zwischen GUI-Objekten und algorithmischen Elementen.

Ziel der folgenden Ausführungen ist es, ein didaktisches Konzept

vorzustellen, bei dem von Anfang an objektbasierte Erklärungsmodelle benutzt werden, um das Verständnis der recht komplexen Delphi-

Programme zu erleichtern.

Diese Vorgehensweise hat zweierlei Vorzüge: Zum wird mit Hilfe der Erklärungsmodelle die "Logik der Programme" vereinfachend dargestellt und somit der Quelltext strukturell geordnet. Zum anderen werden

hierdurch bereits wichtige Konzepte der objektorientierten Modellierung und Programmierung für eine später zu erfolgende Vertiefung eingeführt.

Letzteres erfordert, dass die Grundideen und die Terminologie der

Objektorientierung von Beginn an korrekt und konsistent verwendet

werden.

(3)

3

Teil 1

"Hallo Welt"

-

objektbasierte Benutzungsoberflächen

(4)

4

"Hallo Welt"

(5)

5

GUI-Objekte

Eine Benutzungsoberfläche wird mit Hilfe von sog. GUI-Objekten aufgebaut. (GUI: Graphical User Interface)

GUI-Objekt

Die Eigenschaften eines Objekts kann man sich mit dem Objektinspektor anzeigen lassen.

GUI-Objekt

GUI-Objekt

GUI-Objekt GUI-Objekt

(6)

6

Objekt

Ein Objekt hat (in der Regel) einen Namen und wird einer Klasse zugeordnet. Die Klasse legt dabei den Typ des Objekts fest.

iBaer1:

TImage

Im Objektinspektor werden der Name und die

zugehörige Klasse des markierten Objekts angezeigt.

iBaer1:

TImage

iBaer2:

TImage

bTag:

TButton bNacht:

TButton pAnzeige:

TPanel

GUI:

TGUI

(7)

7

iBaer1:

TImage

Aufbau und Zustand eines Objekts

iBaer1: TImage Visible = False ...

Klasse

Attribut Attributwert

Der Aufbau eines Objekts wird mit Hilfe von Attributen (Eigenschaften) festgelegt. Die Attributwerte legen den aktuellen Objektzustand fest.

Attribut

Attributwert Name

Klasse

Name

(8)

8

Objektdiagramme

iBaer1: TImage Visible = False ...

Um die Struktur von Objekten zu beschreiben, benutzt man sog.

Objektdiagramme.

Objektdiagramm

iBaer2: TImage Visible = True ...

bTag: TButton Caption = 'Tag' ...

bNacht: TButton Caption = 'Nacht' ...

pHinweis: TPanel Caption = 'Wer ...' Color = clGreen ...

GUI: TGUI

Caption = 'Knut ...' Color = clWhite ...

(9)

9

Ein Blick in die Datei „uTagNacht.dfm“

object GUI: TGUI Left = 307

Top = 360

BorderIcons = [biSystemMenu]

BorderStyle = bsSingle Caption = 'Knut tut gut' ClientHeight = 410

ClientWidth = 760 Color = clWhite ...

PixelsPerInch = 96 TextHeight = 16

object iBaer1: TImage Left = 392

Top = 48 Width = 334 Height = 255 AutoSize = True Picture.Data = {

0A544A504547...

...}

Visible = False end

object iBaer2: TImage Left = 32

Top = 48 ...

Visible = False end

object bTag: TButton ...

Caption = 'Tag' TabOrder = 0

OnClick = bTagClick end

object bNacht: TButton ..

end

object pHinweis: TPanel Left = 280

Top = 320 Width = 201 Height = 41 TabOrder = 2 end

end

(10)

10

„verwaltet“

Objekthierarchie

FGUI:

TFGUI

iBaer1:

TImage iBaer2:

TImage bTag:

TButton bNacht:

TButton pHinweis:

TPanel

...

...

...

object GUI: TGUI Left = 307

Top = 360

BorderIcons = [biSystemMenu]

BorderStyle = bsSingle Caption = 'Knut tut gut' ClientHeight = 410

ClientWidth = 760 Color = clWhite ...

PixelsPerInch = 96 TextHeight = 16

object iBaer1: TImage Left = 392

Top = 48 Width = 334 Height = 255 AutoSize = True Picture.Data = {

0A544A504547...

...}

Visible = False end

(11)

11

Veränderung von Objektzuständen

Attributwerte eines Objekts kann man mit Hilfe von Wertzuweisungen verändern.

pHinweis.Caption := 'Pst, ich schlafe!';

pHinweis.Color := clRed;

pHinweis: TPanel Caption = 'Wer ...' Color = clGreen ...

pHinweis: TPanel Caption = 'Pst ...' Color = clRed ...

Objektzustand vorher

Objektzustand nachher

Wertzuweisungen

(12)

12

Ereignisbasierte Veränderung

Ein Ereignis ist eine Zustandsänderung in einem Objekt, die von Interesse ist und daher mit einer Prozedur zur Ereignisverarbeitung verknüpft

werden kann.

(K. Merkert)

Ereignis

Mausklick auf den Button mit der

Aufschrift "Tag" löst das Ereignis

"bTag.onClick" aus

Mausklick auf den Button mit der Aufschrift "Nacht"

löst das Ereignis

"bNacht.onClick" aus

Ereignisverarbeitung

procedure TGUI.bTagClick(Sender: TObject);

begin

GUI.Color := clWhite;

iBaer1.Visible := false;

iBaer2.Visible := true;

pHinweis.Caption := 'Wer spielt mit mir?';

pHinweis.Color := clGreen;

end;

procedure TGUI.bNachtClick(Sender: TObject);

begin

GUI.Color := clBlack;

iBaer1.Visible := true;

iBaer2.Visible := false;

pHinweis.Caption := 'Pst, ich schlafe!';

pHinweis.Color := clRed;

end;

(13)

13

Delphi-Quelltext (uTagNacht.pas)

unit uTagNacht;

interface uses

...

type

TGUI = class(TForm) bTag: TButton;

bNacht: TButton;

iBaer1: TImage;

iBaer2: TImage;

pHinweis: TPanel;

procedure bTagClick(Sender: TObject);

procedure bNachtClick(Sender: TObject);

private

{ Private-Deklarationen } public

{ Public-Deklarationen } end;

var GUI: TGUI;

Deklaration eines

Formulars

mit GUI-Objekten

(14)

14

Delphi-Quelltext (uTagNacht.pas)

implementation {$R *.DFM}

procedure TGUI.bTagClick(Sender: TObject);

begin

GUI.Color := clWhite;

iBaer1.Visible := false;

iBaer2.Visible := true;

pHinweis.Caption := 'Wer spielt mit mir?';

pHinweis.Color := clGreen;

end;

procedure TGUI.bNachtClick(Sender: TObject);

begin

GUI.Color := clBlack;

iBaer1.Visible := true;

iBaer2.Visible := false;

pHinweis.Caption := 'Pst, ich schlafe!';

pHinweis.Color := clRed;

end;

end.

Implementierung

Ereignisverarbeitung der

(15)

15

Teil 2

Bär auf Wanderschaft -

Datenhaltung mit lokalen Variablen

(16)

16

Bär auf Wanderschaft

(17)

17

Bär, komm her!

procedure TGUI.bAktualisierenClick(Sender: TObject);

var

xposPfleger, yposPfleger: integer;

begin

// Eingabe: Übernahme der Anzeige xPosPfleger := StrToInt(eXpos.Text);

yPosPfleger := StrToInt(eYpos.Text);

// Ausgabe: Aktualisierung der Anzeige iPfleger.Left := xPosPfleger;

iPfleger.Top := yPosPfleger;

end; procedure TGUI.bRechtsClick(Sender: TObject);

var

xPosBaer, yPosBaer: integer;

begin

// Eingabe: Übernahme der Anzeige xPosBaer := iBaer.Left;

yPosBaer := iBaer.Top;

// Verarbeitung: Veränderung der Daten xPosBaer := xPosBaer + 10;

// Ausgabe: Aktualisierung der Anzeige iBaer.Left := xPosBaer;

pXposWertBaer.Caption := IntToStr(xPosBaer);

pYposWertBaer.Caption := IntToStr(yPosBaer);

end;

lokale Variable lokale Variable

(18)

18

yXposwertBaer: TPanel Caption = '218'

Caption = '208'...

...

pXposwertBaer: TPanel

Doppelte Buchführung

procedure TGUI.bRechtsClick(Sender: TObject);

var

xPosBaer, yPosBaer: integer;

begin

// Eingabe: Übernahme der Anzeige xPosBaer := iBaer.Left;

yPosBaer := iBaer.Top;

// Verarbeitung: Veränderung der Daten xPosBaer := xPosBaer + 10;

// Ausgabe: Aktualisierung der Anzeige iBaer.Left := xPosBaer;

pXposWertBaer.Caption := IntToStr(xPosBaer);

pYposWertBaer.Caption := IntToStr(yPosBaer);

end;

xPosBaer: 208 iBaer: TImage Visible = True Left = 208 Top = 176 ...

yPosBaer: 176

xPosBaer: 218 yPosBaer: 176

yXposwertBaer: TPanel Caption = '218'

...

iBaer: TImage Visible = True Left = 218 Top = 176 ...

pXposwertBaer: TPanel Caption = '218'

...

(19)

19

yXposwertBaer: TPanel Caption = '218'

Caption = '208'...

...

pXposwertBaer: TPanel

EVA-Prinzip

procedure TGUI.bRechtsClick(Sender: TObject);

var

xPosBaer, yPosBaer: integer;

begin

// Eingabe: Übernahme der Anzeige xPosBaer := iBaer.Left;

yPosBaer := iBaer.Top;

// Verarbeitung: Veränderung der Daten xPosBaer := xPosBaer + 10;

// Ausgabe: Aktualisierung der Anzeige iBaer.Left := xPosBaer;

pXposWertBaer.Caption := IntToStr(xPosBaer);

pYposWertBaer.Caption := IntToStr(yPosBaer);

end;

xPosBaer: 208 iBaer: TImage Visible = True Left = 208 Top = 176 ...

yPosBaer: 176

xPosBaer: 218 yPosBaer: 176

yXposwertBaer: TPanel Caption = '218'

...

iBaer: TImage Visible = True Left = 218 Top = 176 ...

pXposwertBaer: TPanel Caption = '218'

...

Viele Eingabe-Verarbeitung-Ausgabe-Systeme lassen sich mit Hilfe von

lokalen Variablen realisieren.

(20)

20

Teil 3

Bär auf Wanderschaft -

Datenhaltung mit globalen Variablen

(21)

21

Bär, komm her!

Schwierigkeit:

Die Ereignisverarbeitung zum Ereignis "bVorwaerts.Click" hängt von der

momentanen Bewegungsrichtung des Bären ab. Diese Information könnte

man aus den GUI-Objekten gewinnen, indem man nachschaut, welches

Bild gerade sichtbar ist. Besser und übersichtlicher wird das Programm,

wenn man ein internes Datenmodell mit "globalen Variablen" erstellt, auf

die jede Ereignisverarbeitungsprozedur zugreifen und die sie verändern

kann.

(22)

22

Bär, komm her!

...

type

TGUI = class(TForm) bRechts: TButton;

...

procedure bRechtsClick(Sender: TObject);

...

procedure FormCreate(Sender: TObject);

private

{ Private-Deklarationen } xpos, ypos: integer;

oben, unten, links, rechts: boolean;

procedure ausgangslage;

procedure vorwaerts;

procedure rueckwaerts;

procedure rechtsdrehen;

procedure linksdrehen;

procedure baerZeigen;

public

{ Public-Deklarationen } end;

Formular-Attribut als

"globale Variable"

Formular-Methode als Hilfsprozedur

(23)

23

Trennung: GUI – Datenmodell

type

TGUI = class(TForm) bRechts: TButton;

...

procedure bVorwaertsClick(Sender: TObject);

...

procedure FormCreate(Sender: TObject);

private

{ Private-Deklarationen } xpos, ypos: integer;

oben, unten, links, rechts: boolean;

procedure ausgangslage;

procedure vorwaerts;

procedure rueckwaerts;

procedure rechtsdrehen;

procedure linksdrehen;

procedure baerZeigen;

public

{ Public-Deklarationen } end;

procedure TGUI.vorwaerts;

begin

if oben = true then ypos := ypos - 10

else if unten = true then ypos := ypos + 10

else if links = true then xpos := xpos - 10

else if rechts = true then xpos := xpos + 10;

end;

procedure TGUI.bVorwaertsClick(...);

begin

// Datenmodell aktualisieren vorwaerts;

// Anzeige aktualisieren baerZeigen;

end;

Datenmodell

(24)

24

Trennung: GUI – Datenmodell

type

TGUI = class(TForm) bRechts: TButton;

...

procedure bVorwaertsClick(Sender: TObject);

...

private

{ Private-Deklarationen } xpos, ypos: integer;

oben, unten, links, rechts: boolean;

procedure ausgangslage;

procedure vorwaerts;

procedure rueckwaerts;

procedure rechtsdrehen;

procedure linksdrehen;

procedure baerZeigen;

public

{ Public-Deklarationen } end;

procedure TGUI.vorwaerts;

begin

if oben = true then ypos := ypos - 10

else if unten = true then ypos := ypos + 10

else if links = true then xpos := xpos - 10

else if rechts = true then xpos := xpos + 10;

end;

Bei komplexeren Systemen ist es günstig, ein von der GUI getrenntes Datenmodell zu entwickeln.

Datenmodell

(25)

25

Teil 4

Zusammenfassung: Programmmuster

(26)

26

iBaer1: TImage Visible = False ...

iBaer2: TImage Visible = True ...

bTag: TButton Caption = 'Tag' ...

bNacht: TButton Caption = 'Nacht' ...

GUI: TGUI

Caption = 'Knut ...' Color = clWhite ...

Muster 1

GUI-Objekte regeln Anzeige und Kontrolle.

procedure TGUI.bTagClick(Sender: TObject);

begin

GUI.Color := clWhite;

iBaer1.Visible := false;

iBaer2.Visible := true;

pHinweis.Caption := 'Wer spielt mit mir?';

pHinweis.Color := clGreen;

end;

pHinweis: TPanel Caption = 'Wer ...' Color = clGreen ...

(27)

27

Muster 2

EVA - Verarbeitung mit einem temporären Datenmodell

yXposwertBaer: TPanel Caption = '218'

Caption = '208'...

...

pXposwertBaer: TPanel

procedure TGUI.bRechtsClick(Sender: TObject);

var

xPosBaer, yPosBaer: integer;

begin

// Eingabe: Übernahme der Anzeige xPosBaer := iBaer.Left;

yPosBaer := iBaer.Top;

// Verarbeitung: Veränderung der Daten xPosBaer := xPosBaer + 10;

// Ausgabe: Aktualisierung der Anzeige iBaer.Left := xPosBaer;

pXposWertBaer.Caption := IntToStr(xPosBaer);

pYposWertBaer.Caption := IntToStr(yPosBaer);

end;

xPosBaer: 208 iBaer: TImage Visible = True Left = 208 Top = 176 ...

yPosBaer: 176

xPosBaer: 218 yPosBaer: 176

yXposwertBaer: TPanel Caption = '218'

...

iBaer: TImage Visible = True Left = 218 Top = 176 ...

pXposwertBaer: TPanel Caption = '218'

...

(28)

28

Muster 3

Internes Datenmodell mit "globalen Variablen"

type

TGUI = class(TForm) bRechts: TButton;

...

procedure bVorwaertsClick(Sender: TObject);

...

private

{ Private-Deklarationen } xpos, ypos: integer;

oben, unten, links, rechts: boolean;

procedure ausgangslage;

procedure vorwaerts;

procedure rueckwaerts;

procedure rechtsdrehen;

procedure linksdrehen;

procedure baerZeigen;

public

{ Public-Deklarationen } end;

procedure TGUI.vorwaerts;

begin

if oben = true then ypos := ypos - 10

else if unten = true then ypos := ypos + 10

else if links = true then xpos := xpos - 10

else if rechts = true then xpos := xpos + 10;

end;

Datenmodell

(29)

29

Muster 4

Eigenständiges Datenmodell mit neuen Objekten

TRoboter xPos

yPos richtung ...

erzeugen initialisieren schritt

linksDrehen rechtsDrehen markeSetzen markeLoeschen ...

Osten Westen

Süden Norden

(4,3)

Referenzen

ÄHNLICHE DOKUMENTE

• die erste Methode erhält einen Parameter und berechnet die Fläche für ein Quadrat. • die zweite Methode erhält zwei Parameter und berechnet die Fläche für

▶ eine Liste aus Variablen (mit Komma getrennt), die in die Methode gegeben werden (brauchen einen Typen und einen Bezeichner).. Einführung in die Programmierung: by André Karge,Übung

Deswegen fließt die Antwort von Aufgabe 3.a.iii) nicht mit in die Bewertung ein... Einführung in die Programmierung: by André Karge,Übung - Verzweigungen und

// Es wird kein Zustand von vorhandenen Objekten geändert - static public static final Complex add(Complex z1, Complex z2) {. return new Complex(z1.real + z2.real, z1.imag +

private Node front; // Referenz auf das erste Element in der Liste private Node rear; // Referenz auf das letzte Element in der Liste private int nodeCount; // Übersicht, wie

Schreiben Sie Ihre einfach verkettete Liste von letzter Woche um, dass sie anstelle von integer einen Generic Datentypen abspeichert. Testen sie diese generische Liste mit den

• protected = Attribut / Methode einer Klasse mit diesem Keyword sind von allen anderen Klassen nicht sichtbar, außer von child-Klassen.. • private = Attribut / Methode einer Klasse

public class Node <meinVariablerTyp> { // <...> gibt an, dass die Klasse einen generic verwendet private meinVariablerTyp data; // Inhalt von unserem noch nicht