Ustawienia timera wykonującego kod co określoną ilość godzin, minut i sekund

0

Cześć mam mały problem chciałem ustawić wykonanie procedury co określony czas. W 3 Editach podajemy:

  • Edit1 - co ile godzin
  • Edit2 - co ile minut
  • Edit3 - co ile sekund

Wiec zrobiłem tak:

Timer1.Interval:= StrToInt(Edit1.Text)*3600 + StrToInt(Edit2.Text)*60000 + StrToInt(Edit3.Text)*1000;

Czegoś tu nie rozumiem albo liczyć nie umiem. Bo jak zrobiłem tak:

Edit1=0 Edt2=1 Edit3=0
1 minuta = 60 000 milisekund

Kurcze jak to poustawiać by w editach podawać za ile odpowiednio godzin, minut sekund ma się rozpocząć procedura

procedure TForm1Timer1Timer(Sender: TObject);
begin
  Timer1.interval:= Timer1.interval -1;
  Label1.caption:='Czas pozostały: '+ inttostr(Timer1.interval);
 if Timer2.Interval = 0 then
 begin
   SpeedButton1.Click();
 end;
2

Właściwość Timer.Interval zawiera liczbę milisekund, co jaką będzie wykonywał kod zdarzenia OnTimer; Wartość dla tej właściwości należy ustawić raz i czekać aż zadany czas minie; Natomiast w zdarzeniu OnTimer nalezy zapisać kod, który będzie wykonywany po każdorazowym skończeniu odliczania; Przy czym timer sam odmierza czas, więc nie należy mu w tym przeszkadzać;

Poza tym skorzystaj z kontrolek typu TSpinEdit zamiast TEdit - nie będziesz musiał nic konwertować (jest właściwość Value typu Integer), a także zabezpieczać kontrolek przed podaniem nieliczbowych ciągów znaków;

A jeśli już używać komponentów to pasuje im nadać sensowne nazwy, czyli np. dla kontrolek typu TSpinEdit można nadać nazwy pokroju HoursSpin, MinutesSpin i SecondsSpin - od razu wiadomo do czego służą i co zawierają; Dzięki temu obliczenie wartości dla właściwości Timer.Interval mogło by wyglądać tak:

var
  LHours, LMinutes, LSeconds: Integer;
begin
  LHours   := HoursSpin.Value   * 3600000;
  LMinutes := MinutesSpin.Value * 60000;
  LSeconds := SecondsSpin.Value * 1000;

  Timer.Interval := LHours + LMinutes + LSeconds;

Natomiast jeśli masz problem z obliczaniem liczby milisekund dla poszczególnych składowych czasu to zawsze możesz sobie rozbić duże liczby na składowe, które będą dla Ciebie bardziej zrozumiałe:

LHours   := HoursSpin.Value   * 60 * 60 * 1000;
LMinutes := MinutesSpin.Value * 60 * 1000;
LSeconds := SecondsSpin.Value * 1000;
0

To tak chyba zrobiłem?
Na pewno mam tu błąd bo na dzień dobry mi wychodzi start za 0101 (godzinsekund)

Timer1.Interval:= StrToInt(Edit1.Text)*3600000 + StrToInt(Edit2.Text)*60000 + StrToInt(Edit3.Text)*1000;

jak to poprawnie zapisać by odpowiednio podawać godziny minuty i sekundy ?

0

Dziękuję pisząc nie widziałem odpowiedzi :)

0

To tak chyba zrobiłem?

No nie tak zrobiłeś, bo pomyliłeś mnożniki, poza tym w zdarzeniu OnTimer dekrementowałeś wartość właściwości Interval; Tego się nie robi (przynajmniej nie w tym kontekście), a jeśli już robić takie rzeczy to tylko w przypadku, gdy dokładnie wie się co się robi;

jak to poprawnie zapisać by odpowiednio podawać godziny minuty i sekundy ?

Podałem w poprzednim poście.

0

Wybacz że jeszcze raz zagaduje zrobiłem tak jak radziłeś
i działa
Ustawiłem czas czas rozpoczęcia 20 sekund
i w Labelu Czas do końca pojawia się 20000
ale co 20 sekund zmienia się o -1
i pewnie tu poniżej mam jeszcze błąd

procedure TForm1.Timer2Timer(Sender: TObject);
begin
  Timer1.interval:= Timer2.interval -1
  Label1.caption:='Czas pozostały:  ' + inttostr(Timer2.interval);
 if Timer2.Interval = 0 then
 begin
// coś do wykonania
 end;
0

Miałeś racje Dziękuje już poprawiłem swój błąd

0

Wybacz bo szukam rozwiązania dalej.
naprawiłem swoje błędy, przynajmniej tak mi się wydaje :) najważniejsze że działa :)
O co chciałem zapytać;

Jak teraz w Labelu wyświetlić czas pozostały do uruchomienia procedury w taki sposób 0000 (godzin : minut : sekund) odliczany do zera

procedure TForm1.SpeedButtonStartClick(Sender: TObject);
var
  LHours, LMinutes, LSeconds: Integer;
begin
  LHours   := HoursSpin.Value   * 3600000;
  LMinutes := MinutesSpin.Value * 60000;
  LSeconds := SecondsSpin.Value * 1000;
  Form1.ButtonPlay.Click();
  Timer1.Interval := LHours + LMinutes + LSeconds;
  timer1.Enabled := True   ;
 end;

procedure TForm1Timer1Timer(Sender: TObject);
begin
  Label2.caption:='Czas pozostały: '+ inttostr (Timer1.Interval);
  Form1.Next.Click() ;
 timer1.Enabled := False   ;
end;
0
procedure TForm1.SpeedButtonStartClick(Sender: TObject);
var
  LHours, LMinutes, LSeconds: Integer;
begin
  LHours   := HoursSpin.Value   * 3600000;
  LMinutes := MinutesSpin.Value * 60000;
  LSeconds := SecondsSpin.Value * 1000;
  Form1.ButtonPlay.Click();
  Timer1.Interval := LHours + LMinutes + LSeconds;
  TimeToEnd := LHours + LMinutes + LSeconds;
  timer1.Enabled := True   ;
 end;
 
procedure TForm1Timer1Timer(Sender: TObject);
begin
  Label2.caption:='Czas pozostały: '+ inttostr (TimeToEnd);
  Dec(TimeToEnd);
  Form1.Next.Click() ;
  timer1.Enabled := False   ;
end;

Tylko gdzieś musisz sobie zadeklarować zmienną TimeToEnd

Powyżej to tylko przykład bo wyświetli ci tylko ilość milisekund do końca odliczania. Ale używając odpowiednio div sobie możesz to rozbić.

0

Zapisz w Labelu już chyba mam tylko teraz by odliczał

Label1.caption:='Czas pozostały do kolejnego słowa: '+ intToStr(HoursSpin.Value) + ':' +intToStr(MinutesSpin.Value)  + ':' +  intToStr(SecondsSpin.Value);
0

@babubabu:
to chyba nie zadziała, bo odswieżenie labela będzie tak samo częste jak aktywacja onTimer, czyli z interwałem

Timer1.Interval := LHours + LMinutes + LSeconds;

trochę zmodyfikowany kod @babubabu
Timer jest wywoływany co 1 sek w celu bieżącej aktualizacji pozostałego czasu, a po wykonaniu zadanej liczby cykli ( intTimerCounter<=0) wykonuje właściwą akcję

procedure TForm3.btnStartClick(Sender: TObject);
var
  LHours, LMinutes, LSeconds: integer;
begin
  LHours := HoursSpin.Value * 3600;
  LMinutes := MinutesSpin.Value * 60;
  LSeconds := SecondsSpin.Value;
  Timer1.Interval := 1000;
  self.intTimerCounter := LHours + LMinutes + LSeconds;
  Timer1.Enabled := True;
end;

procedure TForm3.Timer1Timer(Sender: TObject);
begin
  self.lblTime.Caption := 'Czas pozostały do kolejnego słowa: '+inttostr(self.intTimerCounter);
  dec(self.intTimerCounter);
  if self.intTimerCounter > 0 then
    exit;
  self.Timer1.Enabled:=false;

  /// tutaj właściwa akcja timera
  ///
  ///

  self.btnStartClick(nil);

end;
0

Gdzie i jak co mam to zadeklarować bo o to się burzy kompilator intTimerCounter

0

w definicji formy np. w sekcji Private

intTimerCounter:integer;
0

Super jest widoczny jakiś czas :) DZIĘKUJĘ
a da się Labelu wyświetlić i odliczać czas w takiej postaci 0000 ?

0

a da się Labelu wyświetlić i odliczać czas w takiej postaci 0000 ?

Da się.

0

A można wiedzieć jak to zapisać poprawnie z góry dziękuję :)

0

Wszystko zależy od tego, jakiego typu jest zmienna przechowująca czas;

Jeśli w zmiennej typu Integer przechowujesz liczbę milisekund (dla timera) to najpierw trzeba będzie z powrotem rozdzielić tę liczbę na składowe (milisekund w godzinach, minutach i sekundach), następnie z każdej składowej pozyskać jej pierwotną postać (ilość godzin, minut i sekund), a na koniec każdą z nich przekonwertować na łańcuch znaków, w dowolny sposób (konkatenacja i funkcja Str czy tam IntToStr lub Format);

Na pewno lepszym rozwiązaniem będzie przechowywanie czasu w zmiennej typu TDateTime, albowiem istnieje do tego typu zestaw funkcji i procedur, służących np. do złączenia składowych w jedną liczbę (funkcja EncodeDateTime), do niej odwrotna, czyli ekstrahująca składowe (funkcja DecodeDateTime lub zlepek HourOf, MinuteOf i SecondOf), a także wygodna funkcja konwertująca TDateTime na łańcuch znaków, według zadanej maski (funkcja FormatDateTime).

0

można uzyć funcji Timetostr, która bez podania dodatkowego parametru formatującego wynik, zamienia czas na string zgodnie z systemowym ustawieniem formatu czasu, albo podając odpowiedni parametr można zdefiniować własny format czasu

 self.lblTime.Caption := 'Czas pozostały do kolejnego słowa: '+timetostr(self.intTimerCounter/24/3600);
0

D Z I Ę K U J Ę :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1