Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Timerabruf (Timer2) bei Timerablauf (Timer1) (https://www.delphipraxis.net/92425-timerabruf-timer2-bei-timerablauf-timer1.html)

Svenkan 19. Mai 2007 15:47


Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Ich möchte Timer2 aufrufen, sobald Timer1 abgelaufen ist. Wenn ich dies über
Delphi-Quellcode:
if TimerReload.Interval<=1 then TimerNextTab.OnTimer(TimerNextTab);
mache, wird dieser aber trotzdem nie abgerufen.

Jürgen Thomas 19. Mai 2007 16:05

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Hallo,

ich verstehe nicht ganz, was Du willst (vor allem wenn ich Deine Konstruktion und Bezeichner lese). Nach Deiner Fragestellung würde ich einfach Folgendes machen:
Delphi-Quellcode:
procedure MyForm.Timer1OnTimer(Sender: TObject);
begin
  Timer1.Enabled := false;
  Timer2.Enabled := true;
end;
Oder was verstehe ich falsch? Jürgen

Svenkan 19. Mai 2007 16:07

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Also ich habe ein Programm, womit ich den aktuellen Vertretungsplan aus einer dbf abrufen und auf dem Monitor anzeigen lasse.
Nun kann man einstellen, wie lange eine Seite eingeblendet sein soll.
Wenn diese Zeit abgelaufen ist, soll TimerNextTab abgerufen werden, damit der jeweilige Wechsel vorgenommen werden kann.
Das Problem ist nur, dass er wenn er auf die letzte Seite wechselt und gleichzeitig der Timer aktiviert wird, er direkt auf den nächsten Tag wechselt.

Jürgen Thomas 19. Mai 2007 16:22

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Aaaahhh! Du willst keinen zweiten Timer aktivieren, sondern einen Timer ein weiteres Mal (ggf. mit anderen Werten) aufrufen. Dann hast Du zwei Sachen nicht verstanden, wie ein Timer arbeitet:
  • Der Timer wird nicht "immer wieder" aufgerufen, bis er abgelaufen ist, sondern einmal (bzw. jedes Mal), wenn seine Gültigkeit endet.
  • Solange Timer.Enabled = true gilt, wird er erneut aktiviert.
  • Das Interval gibt an, nach welcher Zeit er abgelaufen ist.
  • Mögliche Maßnahmen (bei Dir das Umschalten) werden genau zu diesem Zeitpunkt ausgeführt.
Deine if-Abfrage wäre also nur dann wahr, wenn das Interval auf 0/1 gesetzt würde.

Du musst also nach folgendem Schema vorgehen:
Delphi-Quellcode:
private NextTabTimer: TTimer;
//  Startwert auf 5 Sekunden einstellen
NextTabTimer.Interval := 5000;
//  Timer aktivieren, nachdem z.B. Daten eingelesen wurden
NextTabTimer.Enabled := true;
Anzeige.TabIndex := 0;
//  umschalten nach 5 Sekunden
//  weitere Seiten werden 10 Sekunden angezeigt
procedure MyForm.NextTabTimerOnTimer(Sender: TObject);
begin
  NextTabTimer.Interval := 10000;
  //  nach der letzten Tab-Seite deaktivieren, sonst weiterschalten
  if Anzeige.TabIndex = 4
  then NextTabTimer.Enabled := false
  else Anzeige.TabIndex := Anzeige.TabIndex + 1;
end;
Viel Erfolg! Jürgen

Svenkan 19. Mai 2007 16:32

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Also, am besten, ich erklär alles nochmal ganz genau. :D

Also:
AktuSeiten (TabIndex1) bzw. AktuSeitena (TabIndex2) = aktuelle Seiten
TimerReload = holt regelmäßig die Vertretungsdaten
TimerNextTab = Umschalten des TabIndexes

Wenn nun AktuSeite bzw. AktuSeitea = 0 und TimerReload abgelaufen ist (nicht vor dem Umschalten auf AktuSeite = 0, sondern erst, nachdem diese letzte Seite x Sekunden [sprich die Zeit aus dem Timer] angezeigt worden ist!), soll TimerNextTab abgerufen werden.
In diesem soll dann halt das Umschalten geregelt werden (TabIndex0 ---> 1; 1 ---> 2; 2 ---> 0).

Jürgen Thomas 19. Mai 2007 16:47

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Also doch, wie ich es schon in meiner ersten Antwort gesagt habe: die beiden Timer aktivieren und deaktivieren sich gegenseitig.
Delphi-Quellcode:
//  vereinfacht: die Intervalle bleiben konstant
TimerReload.Interval = 30000;
TimerNextTab.Interval = 10000;

//  Anzeige weiterschalten:
procedure MyForm.TimerNextTabOnTimer(Sender: TObject);
begin
  if Anzeige.TabIndex = 2
  then begin
    Anzeige.TabIndex := 0;
    //  das Weiterschalten deaktivieren, damit erst einmal eingelesen werden kann
    TimerNextTab.Enabled := false;
  end
  else begin
    Anzeige.TabIndex := Anzeige.TabIndex + 1;
  end;
end;

//  Daten neu einlesen
procedure MyForm.TimerReloadOnTimer(Sender: TObject);
begin
  if Anzeige.TabIndex = 0
  then begin
    DatenNeuEinlesen();
    //  das Weiterschalten aktivieren
    TimerNextTab.Enabled := true;
  end;
end;
Das Zusammenspiel könnte in der Praxis vereinfacht werden. Eigentlich brauchst Du den TimerReload überhaupt nicht, sondern liest die Daten einfach dann ein, wenn er wieder auf TabIndex 0 umgeschaltet hat. Aber das ist ein anderes Thema.

Gruß Jürgen

Svenkan 19. Mai 2007 16:55

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Ja schon, allerdings funktioniert es so nur richtig beim TabIndex2, wo nur die Meldung angezeigt werden.
Denn wenn ein Tag nur eine Seite hat, dann wird dieser direkt übersprungen. Denn der Timer geht momentan direkt weiter, sobald er auf AktuSeite bzw AktuSeitea = 0 trifft und nicht erst, nachdem diese Seite 0 x Sek angezeigt wurde.

Jürgen Thomas 19. Mai 2007 17:09

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Tut mir leid, dann bin ich nicht mehr fähig zu raten. Wie wäre es, wenn Du uns Deinen bisherigen Code angäbest?!
  • Intervall der beiden Timer
  • Einstellung, wann sie aktiviert werden
  • Code für die Timer-Ereignisse
  • wann und wo/wie die Daten eingelesen werden
Jürgen

Svenkan 19. Mai 2007 17:20

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Reload-Prozedur

Delphi-Quellcode:
procedure TForm2.TimerReloadTimer(Sender: TObject);
var
   Ini: TIniFile;
   y,ya,i,ia,count,count2,counta,countb,ReloadTime,dnr:integer;
   morgen_m: String;
   tomorrow,today: TDateTime;
begin
  dnr:=DayOfWeek(Date);
  if dnr=7 then begin
   today:=Date+2;
   tomorrow:=Date+3;
  end
  else if dnr=6 then begin
   today:=Date+3;
   tomorrow:=Date+4;
  end
  else begin
   today:=Date;
   tomorrow:=Date+1;
  end;

 try
    Ini:=TIniFile.Create(ExtractFilePath(ParamStr(0))+'conf.ini');
    ReloadTime:=(Ini.ReadInteger('Zeiteinstellungen','Tagwechsel',10)*1000);
    morgen_m:=Ini.ReadString('Zeiteinstellungen','Datum morgen',DatetoStr(tomorrow));
    if StrToDate(morgen_m)<tomorrow then morgen_m:=DateToStr(tomorrow)
    else tomorrow:=StrToDate(morgen_m);
  finally
    Ini.Free;
  end;

  if PageControl1.TabIndex=0 then begin
   Label5.Caption:='Vertretungsplan für den';
   Label6.Caption:=DateToStr(today)+' (heute)';
  end
  else if PageControl1.TabIndex=1 then begin
   Label5.Caption:='Vertretungsplan für den';
   Label6.Caption:=DatetoStr(tomorrow);
  end
  else begin
   Label5.Caption:='Meldungen';
   Label6.Caption:='';
  end;

  TimerReload.Interval:=ReloadTime;

 if PageControl1.TabIndex=0 then begin

  if aktuseite = Gesseiten then
    count := length(Daten) mod 19
  else
    count := 19;
  y:= 19*AktuSeite;
  stringgrid1.RowCount:=count+1;
  for i:=0 to count-1 do begin
    stringgrid1.Cells[0,i+1]:= Daten[i+y].klasse;
    stringgrid1.Cells[1,i+1]:= Daten[i+y].stunde;
    stringgrid1.Cells[2,i+1]:= Daten[i+y].fuer;
    stringgrid1.Cells[3,i+1]:= Daten[i+y].wer;
    stringgrid1.Cells[4,i+1]:= Daten[i+y].fach;
    stringgrid1.Cells[5,i+1]:= Daten[i+y].raum;
    stringgrid1.Cells[6,i+1]:= Daten[i+y].bemerkung;
  end;

  if AktuSeite = GesSeiten then
    AktuSeite := 0
  else
    AktuSeite:=AktuSeite+1;
 end
 else if PageControl1.TabIndex=1 then begin

  if aktuseitea = Gesseitena then
    counta := length(Daten2) mod 19
  else
    counta := 19;
  ya:= 19*AktuSeitea;

  stringgrid2.RowCount:=counta+1;
  for ia:=0 to counta-1 do begin
    stringgrid2.Cells[0,ia+1]:= Daten2[ia+ya].klasse;
    stringgrid2.Cells[1,ia+1]:= Daten2[ia+ya].stunde;
    stringgrid2.Cells[3,ia+1]:= Daten2[ia+ya].fuer;
    stringgrid2.Cells[2,ia+1]:= Daten2[ia+ya].wer;
    stringgrid2.Cells[4,ia+1]:= Daten2[ia+ya].fach;
    stringgrid2.Cells[5,ia+1]:= Daten2[ia+ya].raum;
    stringgrid2.Cells[6,ia+1]:= Daten2[ia+ya].bemerkung;
  end;

  if AktuSeitea = GesSeitena then
    AktuSeitea := 0
  else
    AktuSeitea:=AktuSeitea+1;
 end;

TimerNextTab.Enabled:=True;
end;
NextTab-Timer:

Delphi-Quellcode:
procedure TForm2.TimerNextTabTimer(Sender: TObject);
var Ini: TIniFile;
    dnr,interval: Integer;
    morgen_m: String;
    tomorrow,today: TDateTime;
begin
  dnr:=DayOfWeek(Date);
  if dnr=7 then begin
   today:=Date+2;
   tomorrow:=Date+3;
  end
  else if dnr=6 then begin
   today:=Date+3;
   tomorrow:=Date+4;
  end
  else begin
   today:=Date;
   tomorrow:=Date+1;
  end;

 try
    Ini:=TIniFile.Create(ExtractFilePath(ParamStr(0))+'conf.ini');
    interval:=(Ini.ReadInteger('Zeiteinstellungen','Tagwechsel',10)*1000);
    morgen_m:=Ini.ReadString('Zeiteinstellungen','Datum morgen',DatetoStr(tomorrow));
    if StrToDate(morgen_m)<tomorrow then morgen_m:=DateToStr(tomorrow)
    else tomorrow:=StrToDate(morgen_m);
  finally
    Ini.Free;
  end;

if PageControl1.TabIndex=0 then
    begin
    PageControl1.TabIndex:=1;
    TimerNextTab.Enabled:=False;
    TimerNextTab.Interval:=interval;
    Label5.Caption:='Vertretungsplan für den';
    Label6.Caption:=DateToStr(today)+' (heute)';
    end
    else
      if PageControl1.TabIndex=1 then
        begin
          PageControl1.TabIndex:=2;
          TimerNextTab.Enabled:=False;
          TimerNextTab.Interval:=interval;
          Label5.Caption:='Vertretungsplan für den';
          Label6.Caption:=DateToStr(Tomorrow);
        end
        else
          if PageControl1.TabIndex=2 then
            begin
            PageControl1.TabIndex:=0;
            TimerNextTab.Enabled:=False;
            TimerNextTab.Interval:=interval;
            Label5.Caption:='Meldungen';
            Label6.Caption:='';
            end
end;
Der Interval wird jeweils aus einer Ini-Datei ausgelesen.

Jürgen Thomas 19. Mai 2007 18:07

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Hallo Svenkan,

dringende Empfehlung: Strukturiere Deinen Code übersichtlicher:
  • Code-Teile, die sich wiederholen, werden ausgelagert (z.B. interval aus Ini einlesen; date/tomorrow bestimmen).
  • Bleibt das Interval nicht konstant während eines Programmlaufs? Wenn ja, dann gehört das nach FormOnCreate o.ä.
  • "Richtige" Abläufe gehören nicht in die Ereignisprozedur, sondern in eigene Prozeduren. (Das habe ich durch meine Prozedur DatenNeuEinlesen angedeutet.)
  • Einrückungen konsequent beachten: immer 2 Zeichen; was zusammengehört, steht übereinander (try-finally).
Nachtrag: Kommentare helfen ebenfalls sehr. Ich glaube nicht, dass Du übermorgen noch durch Deinen Code durchblickst.

Im Moment erschwerst Du mir/uns das Verständnis viel zu sehr. Du willst schließlich Hilfe; also solltest Du uns dies erleichtern.

Gruß Jürgen

Jürgen Thomas 20. Mai 2007 09:35

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Hallo Svenkan,

mir sind jetzt noch ein paar Gedanken gekommen; die möchte ich mit meinen früheren Vorschlägen zusammenfassen.

1. Einmalige Maßnahmen gehören in den Aufbau des Formulars.
Also interval bestimmen, today, tomorrow

2. Anzeige aktualisieren gehört in eigene Prozeduren:
Delphi-Quellcode:
procedure MyForm.StringGrid1Zeigen(dieseSeite: integer);
begin
  ...
end;
procedure MyForm.StringGrid2Zeigen(dieseSeite: integer);
begin
  ...
end;
3. Daten einlesen gehört in eine eigene Prozedur.
Hier werden auch die Einstellungen vorgenommen, die nur dafür geändert werden müssen:
Delphi-Quellcode:
procedure MyForm.NeueDatenEinlesen;
begin
  //  Einstellungen auf "Einlesen" umschalten
  PageControl1.TabIndex := 2;
  Label5.Caption:='Meldungen';
  Label6.Caption:='';
  TimerNextTab.Enabled := false;
  //  Daten einlesen
  ...
  //  erste Seite zur Anzeige vorbereiten
  AktuSeite := 0;
  StringGrid1Zeigen((0);
  //  Einstellungen auf "Anzeigen" umschalten
  Label5.Caption:='Vertretungsplan für den';
  Label6.Caption:=DatetoStr(tomorrow);
  PageControl1.TabIndex := 0;
  //  und natürlich das Umschalten aktivieren
  TimerNextTab.Enabled := true;
end;
4. Die Timer-Aktion reduziert sich auf einen Verteiler.
Das ist unbedingt die wichtigste Änderung, die Du vornehmen musst!
Delphi-Quellcode:
procedure TForm2.TimerNextTabTimer(Sender: TObject);
begin
  case PageControl1.TabIndex of
    0: begin
         PageControl1.TabIndex := 1;
         StringGrid2Zeigen(AktuSeite);
    1: if (AktuSeite < GesSeiten)
       then begin
         Inc(AktuSeite);
         StringGrid1Zeigen(AktuSeite);
         PageControl1.TabIndex := 0;
       end
       else begin
         NeueDatenEinlesen;
       end;
    2: //  kommt eigentlich wegen NeueDatenEinlesen gar nicht mehr vor,
       //  aber vielleicht ergibt sich noch etwas, deshalb dummy-Code:
       begin
       end;
end;
Ich habe die Unterscheidungen bei AktuSeite(a) und GesSeiten(a) nach wie vor nicht verstanden. Weil das interval der beiden Timer gleich ist, verstehe ich auch nicht, warum Du zwei Timer haben willst.

Versuch doch einmal eine solche Struktur und berücksichtige meine Bemerkungen im letzten Post. Jürgen

Jürgen Thomas 21. Mai 2007 08:14

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Hallo Svenkan,

noch ein Gedanke, wenn Du wirklich zwei Timer nutzen willst. Das kann sinnvoll sein, wenn ihr Intervall ziemlich unterschiedlich festgelegt wird (z.B. 15 Minuten für Reload und 10 Sekunden für NextTab).

TimerReload wird aktiviert (Enabled := true), nachdem die Daten eingelesen wurden, d.h. am Ende der Prozedur NeueDatenEinlesen.

TimerReloadOnTimer macht nichts anderes als sich zu deaktivieren: TimerReload.Enabled := false;

Die Prüfung innerhalb NextTab wird einfach erweitert, ob TimerReload abgelaufen ist oder nicht, d.h. ob er noch aktiviert ist:
Delphi-Quellcode:
procedure TForm2.TimerNextTabTimer(Sender: TObject);
begin
  case PageControl1.TabIndex of
    0: begin
         PageControl1.TabIndex := 1;
         StringGrid2Zeigen(AktuSeite);
    1: if ((AktuSeite < GesSeiten) or TimerReload.Enabled)
       //  die vorstehende Abfrage wird erweitert
       then begin
         //  wenn TimerReload noch läuft, dann zurück zu Seite 0
         if (AktuSeite < GesSeiten)
         then Inc(AktuSeite)
         else AktuSeite := 0;
         StringGrid1Zeigen(AktuSeite);
//  alles andere bleibt wie gehabt
Jürgen

PS. Ich weiß nicht, ob Du meine vorigen Beiträge bereits gelesen hast; deshalb trage ich es als neuen Beitrag ein.

QuickAndDirty 21. Mai 2007 09:40

Re: Timerabruf (Timer2) bei Timerablauf (Timer1)
 
Also grundsätzlich gibt es kaum Gründe mehr als einen Timer pro Anwendung zu verbauen.
Es sei denn man braucht ab und zu einen hochauflösenden Timer und ansonsten einen nicht so hoch auflösenden Timer.

Warum lehrt man in der Schulde schon GUI Programmierung bevor die Programmierprache beherrscht wird?


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:29 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz