Hallo,
 
die CASE Version ist meiner Meinung nach auch übersichtlicher. Aber Du wolltest ja eine funktionierende Version mit if then else
Code: Alles auswählen
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if (Shape1.Brush.Color = clWhite) and (Shape2.Brush.Color = clWhite) and (Shape3.Brush.Color = clWhite) then
   Shape1.Brush.Color := clRed
  else if (Shape1.Brush.Color = clRed) and (Shape2.Brush.Color = clWhite) then
   Shape2.Brush.Color := clYellow
  else if (Shape1.Brush.Color = clRed) and (Shape2.Brush.Color = clYellow) then
  begin
   Shape1.Brush.Color := clWhite;
   Shape2.Brush.Color := clWhite;
   Shape3.Brush.Color := clLime;
  end else if (Shape3.Brush.Color = clLime) then
  begin
   Shape3.Brush.Color := clWhite;
   Shape2.Brush.Color := clYellow;
  end else
  begin
   Shape1.Brush.Color := clRed;
   Shape2.Brush.Color := clWhite;
  end;
end;
Das geht zwar, ist aber nur schwer zu lesen und vor allem zu verstehen.
Spätestens wenn Deine Programme größer werden, wird diese Vorgehensweise schnell unübersichtlich.
Am Anfang etwas schwieriger zu verstehen, aber später ungemein hilfreich ist, Properties zu verwenden.
Als erstes deklarierst Du einen Datentyp, welcher nur die möglichen Ampelzustände definiert.
Am besten oberhalb der Definition des Formulares, weil Du diesen neuen Datentyp dann auch gleich im Formular verwenden kannst.
Code: Alles auswählen
type
  // Typ, welcher die möglichen Ampelstellungen definiert
  TAmpelstatus = (asRot, asRotGelb, asGruen, asGelb);
 
  { TForm1 }
 
  TForm1 = class(TForm)
    BitBtn1: TBitBtn; 
   ...
Im Formular deklarieren wir ein Feld fAmpelstatus vom Typ TAmpelstatus und zwar im privaten Bereich des Formulares sowie eine Procedure SetAmpelstatus.
Im public Teil des Formulares deklarierst Du eine property Ampelstatus.
Diese Property kannst Du im Programm verwenden wie eine Variable, also einen Wert zuweisen oder den aktuellen Wert abfragen.
Einfach durch eine Zuweisung der Form
wird automatisch das richtige Shape mit der richtigen Farbe befüllt.
Das klingt am Anfang vielleicht etwas umständlich, erleichtert aber später das Leben erheblich.
Hier die Definition
Code: Alles auswählen
TForm1 = class (TForm)
   ...
  private
    { private declarations }
    fAmpelstatus : TAmpelstatus;
    procedure SetAmpelstatus(Value : TAmpelstatus);
  public
    { public declarations }
    property  Ampelstatus : TAmpelstatus read fAmpelstatus write SetAmpelstatus;
  end;
Durch die Angabe write SetAmpelstatus bei der Definition der property Ampelstatus ruft der Compiler automatisch die angegebene Procedure auf, wenn der "Variablen" Ampelstatus ein Wert zugewiesen wird und zwar egal wie oder wo.
Diese Procedure ist die einzige Stelle im Programm, welche sich um die richtigen Farbgebungen kümmert.
Du könntest z.B. in Deinem Formular noch 4 Radiobuttons mit "Rot", "Rot/Gelb", "Grün" und "Gelb" einfügen und in der jeweiligen Ereignisbehandlungsroutine für OnClick
schreiben: Ampelstatus := asRot;
Die Implementierung der Methode (so werden Prozeduren und Funktionen genannt, wenn Sie in einer Klasse verwendet werden) SetAmpelstatus schaut dann so aus.
Code: Alles auswählen
procedure TForm1.SetAmpelstatus(Value: TAmpelstatus);
begin
  if (fAmpelstatus <> Value) then
  begin
    fAmpelstatus := Value;
    Shape1.Brush.Color := clWhite;
    Shape2.Brush.Color := clWhite;
    Shape3.Brush.Color := clWhite;
    case fAmpelstatus of
     asRot     :  Shape1.Brush.Color := clRed;
     asRotGelb : begin
                  Shape1.Brush.Color := clRed;
                  Shape2.Brush.Color := clYellow;
                 end;
     asGelb    : Shape2.Brush.Color := clYellow;
     asGruen   : Shape3.Brush.Color := clLime;
    end;
  end;
end;
Der Einfachheit halber definiert man nun noch eine Methode mit dem Namen "NextStatus", welche dem aktuellen Status der Ampel entsprechend den nächsten richtigen
Schaltzustand einstellt.
Unter public fügst Du einfach 
 ein und die Implementation sieht so aus:
Code: Alles auswählen
procedure TForm1.NextStatus;
begin
  case Ampelstatus of
   asRot     : Ampelstatus := asRotGelb;
   asRotGelb : Ampelstatus := asGruen;
   asGruen   : Ampelstatus := asGelb;
   asGelb    : Ampelstatus := asRot;
  end;
end;
Im OnClick des Buttons rufst Du diese nun einfach auf:
Code: Alles auswählen
procedure TForm1.BitBtn2Click(Sender: TObject);
begin
 NextStatus;
end;
Im Anhang ist das Projekt nochmal zum Nachvollziehen. Hier ist noch ein zusätzliches Feld fUpdating vorhanden.
Hintergrund ist folgender. Wenn der Button die Ampel auf die nächste Stufe schaltet, soll auch der entsprechende Radiobutton aktiviert werden.
Da dieser aber wiederum in seinem OnClick Event den Status der Ampelschaltung ändert, käme es zu einer Endlosschleife.
Gruß
 Michl