Qualifikationsphase 1
Beim Start des Reaktionstestes wird die Ampel auf "rot" geschaltet. Nach einem zufällig vom Rechner bestimmten Zeitraum wird die Ampel auf "grün" umgeschaltet. Sobald dies geschieht, muss eine beliebige Taste gedrückt werden. Die Zeitspanne zwischen Umschalten und Reagieren wird in Millisekunden angegeben.

|
type |
Betrachten wir zunächst einen Teil des Quelltextes. Das Formular "Main" hat zwei Schaltflächen, ein Textfeld, einen Timer und ein Editierfeld. Diese Komponenten sind Objekte. Auch das Formular ist ein Objekt. Alle Objekte haben Eigenschaften, Attribute und Methoden. Ein Objekt wiederum ist ein Exemplar einer Klasse. Alle Objekte einer Klasse haben gemeinsame Merkmale. Die Klasse ist also die Bauvorschrift für ein Objekt.
Die Komponenten BtTestreihe und BtReaktionstest sind Objekte der Klasse TButton; das Editierfeld EdZeit ist ein Objekt der Klasse TEdit. Die Form Main ist ein Objekt der Klasse TMain. TMain wiederum ist ein Objekt der Klasse TForm. Hier bereits sieht man, dass Klassen von anderen Klassen abgeleitet werden können. Diese Ableitung wird später besprochen.
Attribute sind Objektvariablen und Zustandsvariablen. Hinter den Methoden verstecken sich Prozeduren. Diese werden jedoch nicht innerhalb des Objektes sondern in der dazugehörigen Klasse definiert. Eigenschaften definieren das Aussehen und Verhalten von Objekten. Sie können über den Objektinspektor direkt definiert werden oder zur Laufzeit des Programms verändert werden.
Die Begriffe sollen am Beispiel des Objektes BtTestreihe und an der Klasse TMain verdeutlicht werden. Die Schaltfläche BtTestreihe hat z.B. die Eigenschaft "Caption". Dieser Eigenschaft wird der Text "Neue Testreihe" zugewiesen. Bei einem Klick auf die Schaltfläche wird die Methode "procedure BtTestreiheClick" ausgeführt. Attribute finden wir in der Klasse TButton. Sie regeln z.B. die Funktion des Buttons.
Wie erwähnt werden Attribute nur in Klassen angegeben. Dafür werden in Klassen keine Eigenschaften angegeben. Dies ist verständlich, wenn man sich vergegenwärtigt, dass die beiden Schaltflächen des Formulars unterschiedliche Texte beinhalten sollen. Attribute und Methoden in Klassen werden als Klassendiagramme dargestellt. Für die Klasse TMain sieht das Diagramm wie folgt aus:
| TMain | Klassenname |
| BtTestreihe: TButton BtReaktionstest: TButton EdReaktionsZeit: TEdit LblReaktionsZeit: TLabel TiReaktion: TTimer Ampel: TAmpel Start, Stop: LongInt |
Attribute (Objektvariablen) |
| BtReaktionstestClick() BtTestreiheClick() BtReaktionstestKeyDown() TiReaktionTimer() |
Methoden |
Objektvariablen werden in der Klassendefinition des Hauptformulars TMain festgelegt. Die Objektvariable des Hauptformulars selbst (Main: TMain) ist dagegen im Hauptmodul definiert: var Main: TMain.
Klassen besitzen die Schutzklassen private und public. Der Benutzer eines Objektes kann nur auf Klassendefinitionen zugreifen, die unter public eingetragen sind. Auf die unter private eingetragenen Attribute und Methoden kann er nicht zugreifen. Eintragungen, die sich aus der Gestaltung eines Formulars mit Hilfe des Objektinspektors ergeben und oberhalb der Schutzklassen stehen, sind immer public. Innerhalb einer Unit kann immer auf alle Bestandteile zugegriffen werden. Betrachten wir die Klassendefinition TAmpel des Objekts Ampel. Ampel ist als Objektvariable im Hauptformular definiert, d.h. das Hauptformular greift auf die Unit Ampel zu. Der Zugriff kann jedoch nur über die in public eingetragenen Methoden erfolgen. Auf die Variable AmpelGruen kann nicht zugegriffen werden. Sie wird vom Objekt Ampel selbst verwaltet.
| type { TAmpel } TAmpel = class(TForm) Shape1: TShape; Shape2: TShape; private { private declarations } zGruen: Boolean; public { public declarations } procedure Rot; procedure Gruen; function IstGruen: Boolean; end; |
Im Unterricht haben wir keine Shapes benutzt: die Ampeln wurden direkt auf ein Canvas gezeichnet. Dabei ergab sich jedoch das Problem, dass die Ampeln nicht nachgezeichnet wurden, wenn ein anderes Fenster die Ampel überlagert. Durch Nutzung des OnPaint- oder OnResize-Ereignisses lassen sich die Ampeln jedoch problemlos auf ein Canvas zeichnen. Im folgenden ist ein funktionsfähiges Programm gelistet.
| unit Reaktionstest; (* Die folgende Zeile gilt nur für Lazarus *) {$mode objfpc}{$H+} interface (* Die folgende uses-Anweisung gilt fürt Delphi *) uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Ampel; (* Die folgende uses-Anweisung gilt fürt Lazarus *) uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,Ampel,LCLIntf; type TMain = class(TForm) BtTestreihe: TButton; BtReaktionstest: TButton; TiReaktion: TTimer; EdReaktionszeit: TEdit; LblReaktionszeit: TLabel; procedure BtTestreiheClick(Sender: TObject); procedure BtReaktionsTestClick(Sender: TObject); procedure BtReaktionstestKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState) procedure TiReaktionTimer(Sender: TObject); private Ampel: TAmpel; Start, Stop: Longint; public { Public-Deklarationen } end; var Main: TMain; implementation (* Die folgende Zeile gilt für Delphi *) {$R *.DFM} (*Die folgende Zeile gilt für Lazarus *) {$R *.lfm} procedure TMain.BtTestreiheClick(Sender: TObject); begin Ampel := TAmpel.Create (Main); Ampel.Show; Ampel.Rot; BtReaktionstest.Enabled := True; end; procedure TMain.BtReaktionsTestClick(Sender: TObject); begin EdReaktionszeit.Text := ''; Ampel.Rot; TiReaktion.Interval := 2000 + Random(3000); TiReaktion.Enabled := True; end; procedure TMain.TiReaktionTimer(Sender: TObject); begin Ampel.Gruen; Start := GetTickCount; TiReaktion.Enabled := False; end; procedure TMain.BtReaktionsTestKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin Stop := GetTickCount; if BtReaktionstest.Enabled then if Ampel.IstGruen then EdReaktionszeit.Text := ' ' + IntToStr(Stop-Start) + ' ms'; end; end. __________________________________________________________________________________________________________________________________ unit Ampel; (* Die folgende Zeile gilt nur für Lazarus *) {$mode objfpc}{$H+} interface (* Die folgende uses-Anweisung gilt fürt Delphi *) uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; (* Die folgende uses-Anweisung gilt fürt Lazarus *) uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls; type TAmpel = class(TForm) procedure FormResize(Sender: TObject); procedure FormPaint(Sender: TObject); private XRot, YRot, XGruen, YGruen: Integer; AmpelBreite: Integer; zGruen: Boolean; procedure AmpelZeichnen; public constructor Create (Sender: TComponent); procedure Rot; procedure Gruen; function IstGruen: Boolean; end; implementation (* Die folgende Zeile gilt für Delphi *) {$R *.DFM} (*Die folgende Zeile gilt für Lazarus *) {$R *.lfm} constructor TAmpel.Create (Sender: TComponent); begin inherited Create (Sender); Canvas.Pen.Width := 3; end; procedure TAmpel.Rot; begin zGruen := False; AmpelZeichnen end; procedure TAmpel.Gruen; begin zGruen := True; AmpelZeichnen end; function TAmpel.IstGruen: Boolean; begin IstGruen := zGruen end; procedure TAmpel.FormResize (Sender: TObject); var Raster: Integer; begin ClientHeight := ClientWidth * 2; Raster := ClientWidth div 10; AmpelBreite := 8 * Raster; XRot := Raster; YRot := 9 * Raster; XGruen := Raster; YGruen := 18 * Raster; AmpelZeichnen; end; procedure TAmpel.AmpelZeichnen; begin with Canvas do begin Brush.Color := clWhite; Rectangle (-3,-3,Width+3,Height+3); if zGruen then begin Brush.Color := clLime; Ellipse (XGruen,YGruen,XGruen+AmpelBreite,YGruen-AmpelBreite); Brush.Color := clGray; Ellipse(XRot,YRot,XRot+AmpelBreite,YRot-AmpelBreite); end else begin Brush.Color := clRed; Ellipse(XRot,YRot,XRot+AmpelBreite,YRot-AMpelBreite); Brush.Color := clGray; Ellipse (XGruen,YGruen,XGruen+AmpelBreite,YGruen-AmpelBreite); end end end; procedure TAmpel.FormPaint (Sender: TObject); begin AmpelZeichnen end; end. |