Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Uhr ohne Hilfe vom "Ttimer" erstellen (https://www.delphipraxis.net/150806-uhr-ohne-hilfe-vom-ttimer-erstellen.html)

poloroyd 27. Apr 2010 18:31


Uhr ohne Hilfe vom "Ttimer" erstellen
 
moin moin,

ich hab da eine kurze Frage an euch, ihr lieben. Und zwar haben wir als 12KlasseKurs eine schwierige Hausaufgabe gekriegt:

Wir sollen eine analoge und eine digitale Uhr erstellen (mit Sekundenzeiger) ohne Hilfe vom "Ttimer"...wie bitte ??? :wall:

weiss echt nicht wie das gehen soll...hat einer von euch eine idee ?? wäre echt nett wenn ihr mir helfen würdet. mfg Jessica. :cat:

Wolfgang Mix 27. Apr 2010 18:44

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Schaue einmal

hier

DeddyH 27. Apr 2010 18:46

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Hallo und Willkommen in der DP :dp:,
mir fällt da spontan eine gewollte Endlosschleife ein (am Besten in einem Thread), die laufend die Uhrzeit abfragt und die Uhr ggf. zeichnet.

SirThornberry 27. Apr 2010 18:49

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Wie genau lautet die Aufgabenstellung? Wenn wirklich nur TTimer verboten ist würde ich einfach die Api-Funktion verwenden um einen Timer zu erstellen. Dort kann man dann auch noch unterscheiden zwischen der Möglichkeit das ganze per Callback oder per Message zu bewerkstelligen.

David Martens 27. Apr 2010 22:21

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Das ist nicht so schwer.

Delphi-Quellcode:

procedure Uhr_starten;
var
  tick : extended;
begin
  tick := Now +     // Now ist eine Funktion zum Holen der Systemzeit
          1 / 3600; // eine Sekunde draufrechnen

  // hier die Uhr starten

  repeat

    while (Now - tick) < 0 do sleep(10); // in 10 Millisekundenschritten warten bis eine Sekunde um ist

    tick := tick + 1 / 3600; // wieder eine Sekunde weiter gehen

    // Uhr neu zeichnen

    Application.ProcessMessages;

  until SpeedButton1.Down;
Zur Erläuterung:
- tick beinhaltet die Zeit der nächsten Sekunde
- Application.ProcessMessages; arbeitet Ereignisse ab, die (für hier) den StopButton abfragen lässt, Oberfläche neu zeichnet ... das kann etwas dauern, daher die Konstruktion mit der Zeit in der Zukunft
- jetzt der StopButton: hier SpeedButton1 mit folgenden wichtigen Eigenschaften allowallup := true und groupindex > 0

Ich hab den Code nicht getestet, aber es soll ja auch noch was übrig bleiben :).

Gruß David

s.h.a.r.k 27. Apr 2010 22:24

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Oder man programmiert sich einen eigenen Timer, der asynchron zum MainThread läuft: Thread der eine Message an den MainThread schickt und in der Execute-Methode ein SleepEx(1000, True) hat :zwinker:

// edit

Für diese Art der Aufgabenstellung wäre es aber etwas übertrieben :spin2:

hathor 28. Apr 2010 22:07

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Der Vorschlag in #5 ist unbrauchbar - da kann man die CPU als Heizung benutzen.

Die Funktion MsgWaitForMultipleObjects ist die Lösung:

Delphi-Quellcode:
function GetTickCount64: Int64; // vermeidet das 49.7-Tage-Problem
var
  QFreq, QCount: Int64;
begin
   Result := GetTickCount;
   if QueryPerformanceFrequency(QFreq) then
   begin
     QueryPerformanceCounter(QCount);
     if QFreq <> 0 then
       Result := (QCount div QFreq) * 1000;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Tick, ms: Int64;
  Event: THandle;
Label go;
begin
go:
  ms:=1000; //millisec
  Event := CreateEvent(nil, False, False, nil);
  try
    Tick := GetTickcount64 + ms;
    while (ms > 0) and
         (MsgWaitForMultipleObjects(1, Event, False, ms, QS_ALLINPUT) <> WAIT_TIMEOUT) do
    begin
      if Application.Terminated then Exit;
      ms := Tick - GetTickcount64;
      Application.ProcessMessages;
    end;
  finally
    CloseHandle(Event);
  end;
Label1.Caption:= TimeToStr(now);
//Uhr zeichnen
Goto go;
end;

Luckie 29. Apr 2010 00:16

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Warum das überflüssige Goto?
Delphi-Quellcode:
finish := not finish;
while not finish do
begin
  // Dein Code
end;

Alaitoc 29. Apr 2010 07:24

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
[OFF-Topic]
Ah GOTO! :duck:
[/OFF-Topic]

MfG Alaitoc

himitsu 29. Apr 2010 07:28

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Moin Jessica,

es wäre aber dennoch nicht schlecht, wenn du mal die gesamte Aufgabenstellung genauer auflisten/beschreiben würdest.

Für eine Aufgabe an Welche, die wohl nicht allzuviel Ahnung von der Matherie haben (Schüler), finde ich die aktuell verstandene Aufgabenstellung etwas schwer/übertrieben/unmöglich.

Angel4585 29. Apr 2010 07:37

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Also ich würde das in nem Thread lösen, ist bissl wie Atombomben auf Eintagsfliegen schmeissen, aber man kommt zum Ziel und soo kompliziert isses au nich.

Also einfach ne eigene Klasse von TThread ableiten und in der Execute-Methode ne "while not Terminated do".
Darin dann ein Label mit der Zeit aktualisieren.

Man muss eigentlich nur beachten synchronize() zu verwenden.

Die restlichen Infos findest im Forum über die Suchfunktion.

hathor 29. Apr 2010 07:49

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Wer das GOTO scheut "wie der Teufel das Weihwasser" kann es auch so abändern:

Delphi-Quellcode:
repeat
.
.
.
until Application.Terminated;

Sherlock 29. Apr 2010 07:56

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Es geht um eine Hausaufgabe in der Schule. Insofern geht alles was über Vorschlag 5 hinausgeht auch über das Niveau der Fragestellung hinaus.

Vorschlag 5 ist mit sicherheit genau das, was der Lehrer erwartet hat.

Sherlock

hathor 29. Apr 2010 08:07

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
@Sherlock:

Delphi-Quellcode:
repeat

    while (Now - tick) < 0 do sleep(10); // in 10 Millisekundenschritten warten bis eine Sekunde um ist
heizt die CPU auf !!!

Mithrandir 29. Apr 2010 08:17

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Zitat:

Zitat von hathor
heizt die CPU auf !!!

Wenns ihr zu warm wird, schaltet sie sich schon aus. :roll: Es wäre halt gut zu wissen, was momentan im Unterricht behandelt wird, dann kann man auch in die richtige Richtung zeigen. Kümmern sie sich um die WinAPI, um unterschiedliche Taktzeiten, Threads... Man kann nur mutmaßen.

DeddyH 29. Apr 2010 08:23

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Die einfachste (wenn auch nicht unbedingt die eleganteste) Möglichkeit ist IMO
Delphi-Quellcode:
while not globale_Boolsche_Variable do
  begin
    Uhr_anzeigen;
    Application.ProcessMessages;
  end;

Sharky 29. Apr 2010 08:33

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Und dazu dann noch Hagens Delay.

DeddyH 29. Apr 2010 08:38

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Wäre schön, aber ob man das dann dem Lehrer erklären kann, steht wieder auf einem anderen Blatt.

xZise 29. Apr 2010 09:32

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Moin,
Zitat:

Zitat von hathor
[...]heizt die CPU auf !!!

Naja das geht. Er wartet immerhin 10 ms bevor er wieder was rechnet. Das heizt die CPU sehr (!) viel mehr auf:
Delphi-Quellcode:
while now - tick < 0 do ;
Wenn man bei Andorra z.B. das Idle Event von Application nimmt und nur Sleep(1); hinzufügt, sinkt die Prozessorlast von 100 % (für ein Kern) auf sehr viel niedrigere Werte. Weil während das Programm schläft arbeitet die CPU (zumindest an diesem Thread) nicht.

MfG
Fabian

Mithrandir 29. Apr 2010 09:37

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Zitat:

Zitat von xZise
Er wartet immerhin 10 ms bevor er wieder was rechnet.

Außerdem sind 10ms für heutige Systeme eine verdammt lange Zeit. ;)

hathor 29. Apr 2010 10:17

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Wo ist eigentlich poloroyd(TE)?

Mithrandir 29. Apr 2010 10:24

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Die hat sicherlich gestern ihrem Lehrer gebeichtet, dass sie die Hausaufgaben nicht hat. Oder spontan von nem Freund kopiert. :mrgreen:

idefix2 29. Apr 2010 16:14

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
@Michael

Delphi-Quellcode:
finish := not finish;
while not finish do
begin
  // Dein Code
end;
Wenn man schon ein überflüssiges goto wegposten will (in diesem Fall sogar berechtigter Weise), dann doch bitte mit Code, der erstens funktioniert und zweitens nicht unnötig kompliziert ist:
Finish := not finish???????
Sollte doch hier heissen:
Finish := false;

Und wozu überhaupt eine unnötige Variable einführen, die an einer anderen stelle im Code deklariert werden muss und zu nichts gut ist?
While true do begin .... end
bzw noch einfacher
repeat .... until false
tuts doch genauso.

Luckie 29. Apr 2010 16:18

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
@Idefix: Die Variable finish kann man in der gleichen ButtonClick Prozedure deklarieren. Dann kann man mit der gleichen Schaltfläche den Vorgang auch wieder abbrechen. Bei deiner Methode ist ein Abbrechen unmöglich.

Ich habe mir dabei schon was gedacht. ;)

Zitat:

Zitat von idefix2
Finish := not finish???????
Sollte doch hier heissen:
Finish := false;

Nein sollte es nicht. Über leg mal, was passiert, wenn man bei meinem Code die Variable mit False initialisiert und was dann bei jedem Klick auf die Schaltfläche passiert?

David Martens 29. Apr 2010 20:27

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
@hathor: Wie ich sehe muß ich hier mein Post verteidigen.

1.
Zitat:

Zitat von hathor
Der Vorschlag in #5 ist unbrauchbar - da kann man die CPU als Heizung benutzen.

Zitat:

while now - tick < 0 do sleep(10);
es wird höchstens 100 mal eine einfache Rechnung gemacht, wenn dir das zu viel ist, dann warte doch einfach länger.
Zu Pascal-Zeiten hat der delay Befehl die CPU geschäftigt, heutzutage legt der sleep Befehl die CPU (für diesen Thread) schlafen, also kann sich CPU ausruhen. Die 10 Millisekunden hab ich gewählt um die Uhr nicht all zu viel nachgehen zu lassen. Bei 10 Millisekunden sind es maximal 10, wenn ich dort 100 eintrage sind es eben 100. Beides ist für den Menschen nicht erkennbar, aber man sollte doch schon schön genau sein.

2.
Zitat:

Zitat von hathor
Die Funktion MsgWaitForMultipleObjects ist die Lösung:

Delphi-Quellcode:
...
Label go;
...
Goto go;
...

Das ist jetzt nicht dein Ernst. Ein goto im Quelltext und der Lehrer wird garantiert eine 6 dafür vergeben, das war ja zu meiner Zeit schon so. Und das soll besser sein als mein Quellcode?

3.
Zitat:

Zitat von hathor
Delphi-Quellcode:
begin
go:
  ms:=1000; //millisec
  Event := CreateEvent(nil, False, False, nil);
  try
    Tick := GetTickcount64 + ms;
    while (ms > 0) and
         (MsgWaitForMultipleObjects(1, Event, False, ms, QS_ALLINPUT) <> WAIT_TIMEOUT) do
    begin
      if Application.Terminated then Exit;
      ms := Tick - GetTickcount64;
      Application.ProcessMessages;
    end;
  finally
    CloseHandle(Event);
  end;
Label1.Caption:= TimeToStr(now);
//Uhr zeichnen
Goto go;
end;

Damit wird deine "Uhr" immer nachgehen. Die Uhr wird die Zeit nachgehen die der Rechner braucht um Application.ProcessMessages; auszuführen.
Meine Uhr geht auch nach, aber der Effekt ist nicht kumulativ, und auch nur für die Berechnung des neuen Ticks.

4.
Es ist eine einfache Schulaufgabe und da sollte man es auch einfach machen. Dein Quellcode kann von einem Schüler nicht stammen.

Gruß David

hathor 29. Apr 2010 20:49

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
@David Martens:

Was Du schreibst ist Unsinn.

1. Ich habe Deinen Code getestet, weil ich wissen wollte, ob mich mein erster Blick trügt:
ich irrte mich nicht: die CPU-Temperatur geht steil nach oben!

2. Wenn ich eine genaue Uhr habe, spielt es keine Rolle, WANN ich auf die Uhr schaue: die Uhrzeit wird immer genau sein - oder verstehst Du nicht, was "Label1.Caption:= TimeToStr(now);" macht?

3. Eine Alternative zu "Goto" habe ich hinzugefügt - weil ich diese krankhafte Abneigung mancher "Programmierer" seit Jahren kenne...

himitsu 29. Apr 2010 20:56

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Delphi-Quellcode:
while now - tick < 0 do ;
Heizt die CPU auf, da der Thread mit 100% CPU-Leisung ständig irgendwas brechnet, vergleicht oder ausließt.

Delphi-Quellcode:
while now - tick < 0 do sleep(10);
Läßt dagegen den Thread die meißte Zeit schlafen.

idefix2 29. Apr 2010 21:47

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
@ Hathor

Auch ohne den Code zu testen - Dein erster Blick trügt Dich. Eine statische Untersuchung des Programmcodes ist in dem Fall absolut trivial:
In der while Schleife wird bei jedem Durchgang eine 10ms lange Pause eingelegt, in der die CPU nichts tut und der Programmthread still liegt. Wenn etwas deine CPU aufheizt, dann ist es sicher nicht diese Schleife.

Ich gehöre nicht auch zu den Fundamentalisten, die lieber drei geschachtelte while-Schleifen mit drei Boolean Variablen und 5 Abfragen machen statt eines einfachen goto, mit dem man sich das theater spart, weil sie das goto scheuen wie der Teufel das Weihwasser. Aber bei deinem Code ist ein goto wirklich fehl am Platz, weil eine "repeat until false" oder eine "while true do" Schleife auf klarere und einfachere Art das gleiche leistet (keine Label-deklaration nötig), und der Code für jeden, der ihn liest, klarer und verständlicher ist als ein Code, der goto enthält: ein Label kann im Prinzip von verschiedenen Stellen aus angesprungen werden, und bindet deshalb zwangsläufig mehr Aufmerksamkeit von dem, der sich in das Programm einlesen muss, als eine Repeat oder while Schleife, wo die Schleifenstruktur explizit klar ist.

idefix2 29. Apr 2010 21:59

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
@ Luckie

Die Idee, die (Endlos)Schleife mit einer Variable abzubrechen, die man durch Klick auf einen Button umschalten kann, ist schon gut, aber erraten konnte man diese Absicht aus Deinem geposteten Code nur schwer. Und der erste Befehl, finish := not finish, bleibt für mich auch in dem Kontext unverständlich, weil es ja vom restlichen Programm abhängt, welchen Wert die Variable finish vorher hat.
Wenn ich überhaupt will, dass die Schleife begonnen wird, ist an der Stelle finish := false eher angebracht, über einen Button kann man dann den variablenwert umschalten und die Schleife abbrechen.

Luckie 29. Apr 2010 22:12

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Nun ja, ich habe eben vorausgesetzt, dass man etwas mitdenkt und meinen Code mehr als Anregung gesehen.

xZise 30. Apr 2010 01:13

Re: Uhr ohne Hilfe vom "Ttimer" erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Moin,
also ich habe jetzt mal deine angebliche Heizung implementiert. Wenn ich die Zeit auf 0 setze, dann hast du recht, aber bei 10 ms zeigt die CPU Werte um 0 % an.
So wie der Code da aber steht ist das nicht eine sondern sind es genau 24 Sekunden ;) Das heißt 3600 * 24 nehmen dann passt es wieder.

Das ist übrigens der Code:
Delphi-Quellcode:
procedure TForm1.BPowerClick(Sender: TObject);
begin
  Tick(0); // Heizt!
end;

procedure TForm1.BSleepClick(Sender: TObject);
begin
  Tick(10); // Heizt nicht!
end;

procedure TForm1.Tick(WaitTime: Integer);
var
  tickTime : extended;
  tckCnt : Byte;
begin
  tickTime := Now + 1 / 86400;

  // Prevent reexecution
  BSleep.Enabled := False;
  BPower.Enabled := False;
  Application.ProcessMessages;
  tckCnt := 0;

  repeat

    while (tickTime - Now) > 0 do
    begin
      sleep(WaitTime); // in 10 Millisekundenschritten warten bis eine Sekunde um ist
    end;

    tickTime := tickTime + 1 / 86400; // wieder eine Sekunde weiter gehen

    Inc(tckCnt);
    lTicks.Caption := IntToStr(tckCnt);
    lTicks.Repaint;
  until tckCnt >= 5;

  BSleep.Enabled := True;
  BPower.Enabled := True;
end;
Außerdem die Auslastung als Anhang. Ich habe einen Quadcore, weshalb selbst die Heiße Variante nur 25 % verbraucht. Ich habe dabei 5 Sekunden zuerst die 10 ms Variante ausgeführt (da wo der rote Strich ist) und dann 5 Sekunden die 0 ms Variante (dort wo der Berg ist). Das am Anfang ist der Programmstart.

MfG
Fabian


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:07 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