Ampelfarben mit Timer aendern

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Moo
Beiträge: 27
Registriert: Mi 21. Mai 2014, 19:11

Ampelfarben mit Timer aendern

Beitrag von Moo »

Hallo liebes forum
Ihr habt mir nun schon so oft geholfen doch ich muss ein weiteres mal darum bitten
Folgendes ist das Thema:
Ich habe ine Ampel erstellt (siehe unten) und will nun dir Farben per timer aendern heisst also dass sich die farbe jeweils nach einer bestimmten Zeit wechselt
Nun kenne ich mich aber mit Timern ueberhaupt nicht aus :/ kann mir jemand vlt erklaeren wie Timer funktionieren und wie ich den hier anwende ? :)

MfG Moo

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
 
  TAmpel = class(TShape)
 
  public
  farbe:integer; //1=rot  2=gelb  3=grün
  constructor create(Besitzer:TComponent); //override;
  procedure paint; override;  //vorhandenes paint überschreiben
 
  end;
 
var
  Form1: TForm1;
  Ampel: TAmpel;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
 Ampel:=TAmpel.Create(Form1);
 Ampel.Parent:=Form1;
 Ampel.farbe:=1;
 Ampel.Left:=80;
 Ampel.Top:=80;
 Ampel.Width:=80;
 Ampel.Height:=234;
 Ampel.Brush.Color:=ClBlack;
end;
 
procedure TForm1.Button2Click(Sender: TObject);
begin
 Ampel:=TAmpel.Create(Form1);
 Ampel.Parent:=Form1;
 Ampel.farbe:=2;
 Ampel.Left:=80;
 Ampel.Top:=80;
 Ampel.Width:=80;
 Ampel.Height:=234;
 Ampel.Brush.Color:=ClBlack;
end;
 
procedure TForm1.Button3Click(Sender: TObject);
begin
 Ampel:=TAmpel.Create(Form1);
 Ampel.Parent:=Form1;
 Ampel.farbe:=3;
 Ampel.Left:=80;
 Ampel.Top:=80;
 Ampel.Width:=80;
 Ampel.Height:=234;
 Ampel.Brush.Color:=ClBlack;
end;
 
constructor TAmpel.Create(Besitzer:TComponent);                     //constructor besondere procedure die etwas erschafft
begin
  inherited Create(Besitzer);
  Parent:=TWinControl(Besitzer);
end;
 
 
procedure TAmpel.paint;
begin
 inherited paint;                                                             //das Alte verwenden
 
 Canvas.Brush.Color:=Brush.Color;
 Canvas.Brush.Style:=BsSolid;
 
 Canvas.Pen.Color:=ClBlack;
 If farbe=1 Then
 begin
  Canvas.Brush.Color:=ClRed;
  Canvas.Ellipse(5,5,75,75);
  Canvas.Brush.Color:=ClGray;
  Canvas.Ellipse(5,81,75,151);
  Canvas.Ellipse(5,158,75,228);
 end;
 
 Canvas.Pen.Color:=ClBlack;
 If farbe=2 Then
 begin
  Canvas.Brush.Color:=ClGray;
  Canvas.Ellipse(5,5,75,75);
  Canvas.Brush.Color:=ClYellow;
  Canvas.Ellipse(5,81,75,151);
  Canvas.Brush.Color:=Clgray;
  Canvas.Ellipse(5,158,75,228);
 end;
 
  Canvas.Pen.Color:=ClBlack;
 If farbe=3 Then
 begin
  Canvas.Brush.Color:=Clgray;
  Canvas.Ellipse(5,5,75,75);
  Canvas.Ellipse(5,81,75,151);
  Canvas.Brush.Color:=ClGreen;
  Canvas.Ellipse(5,158,75,228);
 end;
 
end;
 
 
 
 
end.           

wp_xyz
Beiträge: 5134
Registriert: Fr 8. Apr 2011, 09:01

Re: Ampelfarben mit Timer aendern

Beitrag von wp_xyz »

  • Einen Timer aufs Formular setzen.
  • Interval auf den gewünschten Wert setzen, die Zahl ist in Millisekunden, d.h. du brauchst den Wert 1000 für ein Sekunden-Intervall.
  • Einen Eventhandler für OnTimer schreiben, d.h. was passieren soll, wenn die Intervall-Zeit abgelaufen ist
  • Bei Enabled = true beginnt die Zeit gleich zu laufen, bei false erst, wenn Enabled durch Code, z.B. durch einen Button-Click, auf true gesetzt worden ist.
  • Der Timer läuft so lange, bis er mit Enabled=false deaktiviert wird.
  • Während der Timer läuft wird jedesmal nach Ablauf eines Intervalls das Ereignis OnTimer aufgerufen. Du weißt wahrscheinlich selbst, was du den OnTimer-Handler schreiben musst.
Ein paar Bemerkungen zu deinem Code:
  • Warum hast du das "override" hinter dem Constructor weggemacht? In deinem Code wahrscheinlich egal, aber wenn du die Komponente einmal in die IDE einbinden solltest, wird damit nach dem Einlesen aus der lfm-Datei die Ampel nicht richtig initialisiert.
  • Parent wird im Constructor üblicherweise nicht gesetzt, sondern erst außerhalb, nachdem die Komponente erzeugt ist (so wie du es in Button1Click machst).
  • Zu Button1Click: Das ist eine Methode von TForm1, du rufst darin aber die Instanz Form1 auf. Jetzt auch wieder kein Problem, aber du kannst jederzeit eine zweite Instanz von TForm1 erzeugen, die dann nicht mehr Form1 heißt. In diesem Formular wird dann die Ampel nicht funktionieren. Verwende in Button1Click statt "Form1" den Bezeichner "self", das bezieht sich immer auf die aktuelle Instanz von TForm1 (gilt allgemein).

Moo
Beiträge: 27
Registriert: Mi 21. Mai 2014, 19:11

Re: Ampelfarben mit Timer aendern

Beitrag von Moo »

ok
wie muss ich die procedure jetzt schreiben?
hab leider keine ahnung was ich da schreiben muss .. muss ich im timer was beachten ?
Edit2: also ich meine ich weiss nich ob ich da was beachten musstheoretisch weiss ich was ich schreiben muss


aber wenn ich das jetzt nicht aendern wuerde wuerde es trotzdem funktionieren ?
Edit 1: das mit dem Parent im constructor hat uns unser info lehrer gezeigt :D

wp_xyz
Beiträge: 5134
Registriert: Fr 8. Apr 2011, 09:01

Re: Ampelfarben mit Timer aendern

Beitrag von wp_xyz »

Keine Angst etwas auszuprobieren, kann nichts passieren, schlimmstenfalls stürzt das Programm (selten das Betriebssystem) ab. Dann Änderungen rückgängig machen und auf zum nächsten Versuch.

Aber konkreter:
Den Timer auf das Formular klicken
Die Eigenschaften kannst du vorerst lassen
Doppelklick auf dem Timer --> im Editor erscheint das Gerüst für den OnTimer-Eventhandler. Zwischen "begin" und "end" deinen Code einfügen. Was soll da passieren? Bei jeder Ampel den Farbwert um 1 erhöhen und die Ampel neu zeichnen (Ampel.Invalidate). Was, wenn die Farbe gerade 3 ist? Mehr verrate ich nicht...

Moo
Beiträge: 27
Registriert: Mi 21. Mai 2014, 19:11

Re: Ampelfarben mit Timer aendern

Beitrag von Moo »

ok dankeschoen !

das wird jetzt aber sicherlich noch ne weile dauern bei mir :D
denn alle meine denkansaetze funktionieren nich :D

aber vielen vielen danke ! auch fuer die erkaerung ! *daumen hoch*

Edit1: timer1.Enabled:=True; ist aber richtig oder ?
weil nichts passiert und ich habe mich halt gefragt ob es daran liegt :D

wp_xyz
Beiträge: 5134
Registriert: Fr 8. Apr 2011, 09:01

Re: Ampelfarben mit Timer aendern

Beitrag von wp_xyz »

Schau dir das beigefügte Programm an, es enthält einen Timer, der jede Sekunde das OnTimer-Ereignis erzeugt und dort einen Zähler erhöht und in einem Label anzeigt. Du schaffts es sicher, das auf deine Aufgabenstellung zu übertragen
Dateianhänge
timer.zip
(1.81 KiB) 47-mal heruntergeladen

wp_xyz
Beiträge: 5134
Registriert: Fr 8. Apr 2011, 09:01

Re: Ampelfarben mit Timer aendern

Beitrag von wp_xyz »

Moo hat geschrieben: timer1.Enabled:=True; ist aber richtig oder ? weil nichts passiert
Richtig. Hast du den Eventhandler? Und hast du das Invalidate für die Ampeln aufgerufen? Üblicherweise macht setzt man Farben über Eigenschaften, bei denen das Neuzeichnen automatisch angestoßen wird. Aber bei dir ist die Farbe nur eine Variable, und du musst explizit dafür sorgen, dass sich die Ampel neu zeichnet

Moo
Beiträge: 27
Registriert: Mi 21. Mai 2014, 19:11

Re: Ampelfarben mit Timer aendern

Beitrag von Moo »

Invalidate hab ich aufgerufen
muss dann jetzt ja am eventhandler liegen gut dann bin ich mir in der hinsicht schonmal sicher :)

Moo
Beiträge: 27
Registriert: Mi 21. Mai 2014, 19:11

Re: Ampelfarben mit Timer aendern

Beitrag von Moo »

ok mag jetzt dumm klingen aber ich packs grade einfach nicht mehr oO
so ungefaehr muesste es ja aussehen aber ich finde den Fehler einfach nicht

Code: Alles auswählen

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  farbe:=farbe+1;
  Ampel.Invalidate;
 
  if farbe=3 then
  farbe:=1;
 
 
 
 
 
end; 

wp_xyz
Beiträge: 5134
Registriert: Fr 8. Apr 2011, 09:01

Re: Ampelfarben mit Timer aendern

Beitrag von wp_xyz »

Stimmt fast. Geh das mal in Gedanken durch: Nimm an, die Ampel hat gerade die Farbe rot, wenn das Timer-Ereignis kommt. Mit welcher Farbe wird die Ampel gezeichnet? Ist das richtig? Ist das Statement in der letzten Zeile richtig?

Da kommt mir aber die Idee, dass ich vielleicht deine Aufgabe falsch verstanden habe. So wie dein Code suggeriert, habe ich angenommen, du hättest drei "Ampeln" (= Lampen), deren Farbe jeweils von Rot nach Gelb nach Grün geschaltet wird. Darauf haben meine bisherigen Hinweise abgezielt.

Wahrscheinlich meint der Lehrer aber ein "richtige" Ampel, also 1 Objekt mit drei Lampen, die unterschiedeliche Farben haben und zu unterschiedlichen Zeiten an und aus sind, also in Phase 1 rot an, gelb aus, grün aus, in Phase 2 rot an, gelb an, grün aus, in Phase 3 rot aus, gelb aus, grün an, in phase 4 rot aus, gelb an, grün an. Phase 5 hätte nur rot an, und das ist identisch mit Phase 1.

Wenn das so ist, kann du das bisherige und auch deinen eigenen Code vergessen, und wir müssen von vorn anfangen. Aber nicht verzweifeln, das ist normal, wir kriegen das schon hin.

Moo
Beiträge: 27
Registriert: Mi 21. Mai 2014, 19:11

Re: Ampelfarben mit Timer aendern

Beitrag von Moo »

ok also
ich habe eine Ampel mit 3 lichtern und ich kann diese wechseln

nun mit dem timer soll die ampel von rot nach gelb und nach gruen und dann wieder nach rot wechseln :D

http://www.imgbox.de/show/img/wi68vbt9T6.png hier mal ein bild von der ampel :)

wp_xyz
Beiträge: 5134
Registriert: Fr 8. Apr 2011, 09:01

Re: Ampelfarben mit Timer aendern

Beitrag von wp_xyz »

Also, jede Farbe hat immer dieselbe Farbe, d.h. das Feld "farbe" darf man nicht ändern. Dann fehlt in deiner Klasse-Definition TAmpel aber ein Feld dafür, ob die Ampel ein- oder ausgeschaltet ist. Wenn sie "ein" ist, malst du sie in der "farbe" der Ampel, wenn sie "aus" ist, malst du sie grau.

Code: Alles auswählen

 
type
  TAmpelFarbe = (afRot, afGelb, afGruen);
 
  TAmpel = class(TShape)
  private
    Ein: Boolean;
  public
    Farbe: TAmpelFarbe;
    constructor Create(Besitzer: TComponent); override;
    procedure Paint; override;
    procedure Einschalten;
    procedure Ausschalten;
  end;
 
In der Paint-Methode prüfst du, ob das Feld "Ein" true oder false ist. Entsprechend setzst du den Brush des Ampel-Canvas auf clGray (Ein=false) oder clRed (Ein = true, und Farbe = afRot) bzw. Geld oder Grün.

In der Einschalten-Methode setzst du "Ein" auf true und rufst Invalidate auf, damit sich die Ampel neu zeichet.

In der Ausschalten-Methode setzst du "Ein" auf false und rufst wieder Invalidate auf.

Den Timer würde ich über einen vollen Ampelzyklus laufen lassen, sagen wir 100 OnTimer-Events. Du definierst einen Zähler, der sich mit jedem Timer-Event um 1 erhöht wird, wenn der Zähler die 100 überschritten hat, setze du ihn wieder auf 0 zurück. Sagen wir, die Rot-Phase ist 50 Einheiten lang, gelb 10 und grün 30 und die letzte Gelb-Phase nochmals 10 - das sind zusammen 100 (und Rot ist wie im echten Leben am längsten!). Dann musst du nach den Ändern des Zählerstandes prüfen, in welchem Zustand die drei Lampen sein müssen:

Code: Alles auswählen

 
  // Rot
  if Zaehler < 50 then begin
    Ampel1.Einschalten;
    Ampel2.Ausschalten;
    Ampel3.Ausschalten;
  end else
  // Gelb
  if Zaehler < 50+10 then begin
    Ampel1.Ausschalten;
    Ampel2.Einschalten;
    Ampel3.Ausschalten;
  end else
    // usw. analog für die anderen Lampen...
 
Damit das ganze dann live in vernünftiger Geschwindigkeit abläuft, würde ich aber das Timer-Intervall auf 100 ms setzen, mit der Standardeinstellung würde ein voller Zyklus 100 sekunden dauern.

In der Klassendeklaration habe ich das Feld "Ein" in den "private"-Abschnitt gesetzt, damit man es nicht ändern kann, ohne ein automatisches Neuzeichnen der Ampel zu bekommen. Statt der Methoden Einschalten und Ausschalten könntest du auch Properties deklarieren, aber das ist für den Anfang vielleicht zu viel.
Zuletzt geändert von wp_xyz am So 19. Apr 2015, 22:12, insgesamt 2-mal geändert.

Moo
Beiträge: 27
Registriert: Mi 21. Mai 2014, 19:11

Re: Ampelfarben mit Timer aendern

Beitrag von Moo »

das ist mir glaub fuer heute zu kompliziert

Moo
Beiträge: 27
Registriert: Mi 21. Mai 2014, 19:11

Re: Ampelfarben mit Timer aendern

Beitrag von Moo »

Ampel.Einschalten ist also im entdefekt die farben procedure? also farbe=1 then und so

wp_xyz
Beiträge: 5134
Registriert: Fr 8. Apr 2011, 09:01

Re: Ampelfarben mit Timer aendern

Beitrag von wp_xyz »

Welche Farben-Procedure? In deinem Code im 1.Post ist Farbe eine Variable? Die Farbe ist eine Eigenschaft der Ampel, sie bleibt immer gleich. Du schaltest die Ampel nur "ein" und "aus". In der Paint-Routine verwendest du zum Malen diese Farbe, wenn die Ampel "ein" ist, bzw. eine neutrale Farbe (clGray), wenn die Ampel "aus" ist.

Antworten