Autor |
Beitrag |
BigBasti
      
Beiträge: 45
Win XP
D7
|
Verfasst: Di 31.01.06 22:06
ich habe in mein programm einen timer gepackt, der die Sekunden und Minuten anzeigen soll, doch kommt es zeitweise vor, dass er Sekunden überspringt und zum beispiel von 12:12 (Minuten : Sekunden) auf 12:15 springt. Der Intervall des ontimer ereignisses ist 1000 (also genau eine sekunde), hier mal der code:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure Tform1.Timer1Timer(Sender: TObject); begin if sek<59 then sek:=sek+1 else begin sek:=0; if min<59 then min:=min+1 else min:=0; end;
uhrlabel.caption:='Zeit: ' + inttostr (st) + ':' + inttostr (min) + ' Uhr'; end; |
kann mir jemand helfen, dieses problem zu lösen? wäre supernett 
|
|
UGrohne
      

Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Di 31.01.06 22:17
Wieso nimmst Du dafür nicht die Systemzeit? Dort kannst Du auch bei 0 anfangen, wenn Du zu einem bestimmten Zeitpunkt die Systemzeit abgreifst (z.B. in OnShow):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| type TForm1 = class(TForm) Timer1: TTimer; procedure Timer1Timer(Sender: TObject); procedure FormShow(Sender: TObject); private time: TDateTime; public end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject); begin Caption := TimeToStr(Now-time); end;
procedure TForm1.FormShow(Sender: TObject); begin time := Now; end;
end. |
Der Timer an sich ist halt ein wenig ungenau, da man nicht voraussagen kann, wann die Anwendung wieder Prozess-Zeit zugewiesen bekommt. Aber mit Hilfe der Systemzeit kannst Du vermeiden, dass diese Sprünge Einfluss auf Deine Zähler haben.
|
|
digi_c
      
Beiträge: 1905
W98, XP
D7 PE, Lazarus, WinAVR
|
Verfasst: Mi 01.02.06 09:25
Oder du benutzt einen HighPerformance Timer wie er z.B. bei Spielen eingesetzt wird. Aber ich weiß nicht ob das deinem Problem angemessen ist.
|
|
Muetze1
      
Beiträge: 346
|
Verfasst: Mi 01.02.06 09:36
digi_c hat folgendes geschrieben: | Oder du benutzt einen HighPerformance Timer wie er z.B. bei Spielen eingesetzt wird. Aber ich weiß nicht ob das deinem Problem angemessen ist. |
Dieser ist zum Timing gut, aber nicht zum Triggern. Er hat kein Ereignis und muss daher gepollt werden - bringt daher mehr Nachteile als Vorteile.
_________________ 49 63 68 68 61 62 65 6B 65 69 6E 65 41 68 6E 75 6E 67 21
|
|
BigBasti 
      
Beiträge: 45
Win XP
D7
|
Verfasst: Mi 01.02.06 12:32
vielen dank, ich werde es mal mit der systemzeit versuchen! wenns geklappt hat, sag ich bescheid
edit: joar klappt so weit, nun hab ich aber ein paar fragen zum typ tdatetime!
ich möchte in meinem programm einen "schnelleren tagesablauf" (blöde formulierung) simulieren, deshalb benötige ich nur das anzeigen von Minuten (wobei eine minute einer sekunde in echtzeit ensprechen soll) und der stunden (wobei eine stunde einer minute in echtzeit entsprechen soll, also 60 sekunden in echtzeit). demzufolge soll die ausgabe in etwa wie 23:45 sein (Stunde:Minute), also müsste ich auch noch dafür sorgen, dass die echtzeitminuten im tdatetime nur bis 24 gehen (da sie im programm ja die stunden repräsentieren) und die echtzeitstunden nicht ausgegeben werden.
ist so etwas mit tdatetime verwirklichbar oder gibt es eine andere möglichkeit dies zu erreichen??
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Mi 01.02.06 13:13
Kleiner Nachtrag:
Ein TTimer ist nicht wirklich eine Uhr, die knallhart immer ein Ereignis auslöst (schön wärs). Windows verwaltet diese Timer und verschickt entsprechende WM_TIMER Nachrichten. Das ist natürlich blöd, wenn die Anwendung gerade in einer dicken Schleife ist, und die Nachrichten gar nicht abgearbeitet werden.
Abhilfe: Immer mal wieder 'Application.ProcessMessages' aufrufen. Dann klappt das auch mit dem Timer besser. Da es keine hochpräzise Quarzuhr ist, sondern nur eine Softwarelösung, kann man damit keinen Zähler hochzählen und dann erwarten, daß das Ergebnis genau ist. Die eingebaute Uhr (Time) ist dafür jedoch genau genug (+/- 20ms).
_________________ Na denn, dann. Bis dann, denn.
|
|
digi_c
      
Beiträge: 1905
W98, XP
D7 PE, Lazarus, WinAVR
|
Verfasst: Mi 01.02.06 13:39
Ich habe festgestellt, das es aber auch Probleme gibt, wenn du z.B. mit dem Mauscursor auf die Fensterleisten Symbole(Minimieren,Schließen,..) gehst und dann ein Hint erscheint.
|
|
BigBasti 
      
Beiträge: 45
Win XP
D7
|
Verfasst: Mo 06.02.06 23:06
ok ich habe nun folgendes festgestellt:
wenn ich eine variable mit dem timer mitlaufen lasse (siehe ganz oben) wird dieser zwar tatsächlich jede sekunde ausgelöst (Interval ist 1000) jedoch wird die variable, die eigentlich bei jedem aufruf nur um eins erhöht werden soll, um zwei oder sogar 3 erhöht (und das jede sekunde)!
kann mir jemand diese unregelmäßigkeit erklären? der timer wird doch korrekt aufgerufen oder? warum wird der wert der variable nicht richtig erhöht?
|
|
UGrohne
      

Beiträge: 5502
Erhaltene Danke: 220
Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
|
Verfasst: Mo 06.02.06 23:14
Also ich hab Dein Code oben mal überprüft und es ausprobiert. Bei mir funktioniert das einwandfrei. Wie hast Du denn festgestellt, dass die Variable um mehr als 1 erhöht wird? Mit dem Debugger?
Und wieso nimmst Du nicht die Systemzeit als "Taktgeber", wie ich es Dir oben geschildert habe?
|
|
Spaceguide
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Mo 06.02.06 23:57
Ich habe auch dieses Timer-Problem. Probiert es mal aus: Setzt einen Timer auf das Form, der z.b. einen Wert erhöht und ins MouseMove des Forms ein Sleep(10). Solange man die Maus bewegt wird das TimerEvent nie gefeuert.
|
|
Amateur
      
Beiträge: 777
(Win98, WinMe) WinXP Prof
D3 Prof, D6 Pers, D2k5 Pers., Turbo C++ Explorer
|
Verfasst: Di 07.02.06 00:55
ja vielleicht weil sleep den hauptthread komplett lahm legt und damit auch den timer.. also entweder sleep und nen extra timer thread oder anstatt sleep nen delay selbst schreiben und zwar mit application.processmessages...
_________________ "Kein dummes Gerede. Kein Rumrätseln. Denkt an nichts anderes mehr, nur noch an das, was vor euch liegt. Das ist die wahre Herausforderung. Ihr müßt euch vor euch selbst schützen, Leute." (Rennes in "Cube")
Beiträge: >700
|
|
Spaceguide
      
Beiträge: 552
(D3/D7/D8) Prof.
|
Verfasst: Di 07.02.06 02:05
Aber nach dem Sleep werden wieder Messages verarbeitet bzw. an das Form geschickt, wie z.B. die Mausbewegung. Es wird jedoch nie eine Message an den Timer geschickt.
|
|
King_Crasher
      
Beiträge: 37
WIN XP
Delphi 2003
|
Verfasst: Di 07.02.06 11:52
Der folgende Quelltext zeigt die Systemuhr an:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.Timer1Timer(Sender: TObject); var DateTime : TDateTime; str : string; begin DateTime := Time; str := TimeToStr(DateTime); Caption := str; |
|
|
BigBasti 
      
Beiträge: 45
Win XP
D7
|
Verfasst: Mi 08.02.06 11:06
ich möchte es nicht mit der systemzeit machen, da bei ich etwas aus der zeit auslesen muss und (siehe oben) die minuten in sekundenschritten und die stunden in minutenschritten vergehen sollen, wodurch die systemzeit unpraktisch ist, da ihre minutenschritte logischerweise bis 60 gehen, ich aber diese nur bis 24 laufen lassen möchte. klingt veriwirrend, daher das schema was ich meine:
die systemzeit gibt aus:
04:12:45 (in Stunden/Minuten/Sekundenschritten)
Stunde:Minute:Sekunde
ich möchte das ganze so haben:
12:45 (in Minuten/Sekundenschritten)
Stunde:Minute (deshalb soll der erste wert, der sich ja im minutentakt erhöht, nur bis 24 gehen können)
ich hoffe aus meinen aufzeichnungen wird jemand schlau
Basti
|
|
digi_c
      
Beiträge: 1905
W98, XP
D7 PE, Lazarus, WinAVR
|
Verfasst: Mi 08.02.06 11:49
Schau mal in die DtaeUtils Unit dort sind schöne Befehle zum auseinanderpflücken z.B. Dayof(),DecodeXYZ...
|
|
azubi_20
      
Beiträge: 593
WinXP SP2, Ubuntu 8.4
D7 Enterp., D2005 Prof., Java (Eclipse 3.4.0)
|
Verfasst: Mi 08.02.06 11:51
Also, hier eine Lösung mit einem sicheren Zähler (weil von Systemzeit abgeleitet) :
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48:
| private procedure init;
var std, min, sec, msec : Word; zeit : TDateTime; insec : LongInt; sichererZaehler : LongInt; vtime :TDateTime; initsec : LongInt;
procedure TForm1.init; begin vtime := Now; DecodeTime(vtime, std, min, sec, msec); initsec := std * 3600 + min * 60 + sec; end;
procedure TForm1.Timer1Timer(Sender: TObject); begin DecodeTime(Now, std, min, sec, msec); insec := std*3600 +min*60 +sec;
sichererZaehler := insec-initsec-1;
uhrlabel.Caption := inttostr(sichererZaehler div 60)+' : '+inttostr(sichererZaehler mod 60);
if uhrlabel.Caption = '23 : 59' then init; end;
procedure TForm1.Button1Click(Sender: TObject); begin init; timer1.Enabled := true; end; |
|
|
BigBasti 
      
Beiträge: 45
Win XP
D7
|
Verfasst: Do 09.02.06 08:35
damit sollte es klappen, danke!
ich probiers mal aus und wenn es funktioniert, sag ich bescheid.
|
|