Sekundengenaue Darstellung



  • Hallo zusammen,

    ich möchte gerne über ein Label eine bestimmte Anzahl an Sekunden herunterlaufen lassen und parallel dabei ein CGauge füllen.

    Leider funktioniert dies nur bedingt. Die Darstellung ist nicht zu 100% sekundengenau. Gibt es eine bessere Lösung als diese:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     int rechenzeit    = 60;            //Sekunden
     CGauge1->MaxValue = rechenzeit*100;
     CGauge1->Visible  = true;
    
     for (int i = 1; i <= rechenzeit*100; i++)
         {
          ::Sleep(10);
          Label4->Caption   = "Berechnung abgeschlossen in " + IntToStr(rechenzeit - i/100) + " Sekunden.";
          CGauge1->Progress = i;
          Application->ProcessMessages();
         }
    }
    

    In Zeile 4 und 7, mal 100, damit bei kleinen Rechenzeiten nicht blockweise das CGauge gefüllt wird, sondern auch hier ein flüssiger Übergang zu erkennen ist.

    LG
    Todd



  • Geht es darum, dem Benutzer eine genause Anzeige der Rechenzeit zu vermitteln oder einen schönen flüssigen Übergang unabhängig von der verbleibenden Rechenzeit zu haben ?
    Wenn es genauer sein soll, kannst du das ja in einen Timer setzen.



  • Hallo

    Windows ist kein Echtzeit-Betriebssystem. Du kannst nicht davon ausgehen das Sleep(10) wirklich genau 10 Millisekunden wartet, es könnten auch 9 oder 11 sein.
    Eine höhere Genauigkeit kannst du durch QueryPerformanceCounter erreichen, siehe WinAPI-Forum.

    /Edit : Die Genauigkeit von TTimer ist grade in dem Millisekundenbereich unter 100 auch nicht besser als Sleep (hat dafür aber eine bessere, sprich geringere Auslastung)

    bis bald
    akari



  • Egal wie genau der Timer ist, es ist grundsätzlich Unsinn, den Wert von rechenzeit aus dem Timerintervall zu berechnen.

    Todd, miss die tatsächlich verstrichene Zeit und errechne die Anzeige daraus.



  • Hallo,

    erstmal danke für eure Antworten.

    Es geht um die möglichst genau Darstellung der verbleibenden Rechenzeit.

    Der Nutzer gibt diese vor und schickt danach einen Algorithmus ins Rennen.
    Danach wird ihm angezeigt, wann der Alg. durchgelaufen ist. Einerseits über das Label, und andererseits über die CGauge.

    Wenn keine großen Abweichungen auch in größeren Dimensionen (z.B. 3600 sec = 1 Stunde) zu erwarten sind, könnte ich mit der jetzigen Lösung leben.

    Ansonsten werde ich den Tip der WinAPI Funktion prüfen.

    Gibt es eine einfache Möglichkeit zwei "Zeiten" zu subtrahieren?
    Also in etwa:

    {
     startzeit = jetzt;
     for (int i=1;...)
        {
         ....
         sec = jetzt - startzeit;
         ....
        }
    }
    

    Danke und liebe Grüße
    Todd



  • Hallo

    Ja das geht mit TDateTime. In deinem Fall dürfte aber die bereits genannte WinAPI-Funktion besser sein, die nach genau diesem Pronzip arbeitet aber effizienter ist.

    bis bald
    akari



  • prinzipiell würd ich von der verwendung von

    Application->ProcessMessages();

    abraten, hab nur schlechte erfahrungen damit gemacht, arbeite lieber mit signalen wenn es sein muss, wenn du methoden verschachtelt startest die dan abwechselnd immer wieder Application->ProcessMessages(); aufrufen, gibt das nur ärger



  • Danke für eure Antworten.

    Versuche mal mit der WinAPI Funktion zurechtzukommen.

    LG
    Todd



  • Hallo zusammen,

    habe es jetzt mal mit der WinAPI Funktion realisiert.

    LARGE_INTEGER jetzt, startzeit, pc_freq;
    
     int rechenzeit               = 60;
     int verstrichene_sekunden    = 0;
     CGauge1->MaxValue            = rechenzeit;
     CGauge1->Visible             = true;
     QueryPerformanceCounter(&startzeit);
     QueryPerformanceFrequency(&pc_freq);
    
     while (verstrichene_sekunden < rechenzeit)
     {
      QueryPerformanceCounter(&jetzt);
      verstrichene_sekunden = (jetzt.QuadPart-startzeit.QuadPart)/pc_freq.QuadPart;
      Label4->Caption       = "Berechnung abgeschlossen in " + IntToStr(rechenzeit - verstrichene_sekunden) +" Sekunden.";
      CGauge1->Progress     = verstrichene_sekunden;
      Application->ProcessMessages();
     }
    

    Funktioniert soweit auch ganz gut.

    Jetzt aber eine andere Frage bezüglich dieses Themas:

    Mein CGauge liegt auf einer Toolbar, hinter allen ToolButtons.
    Die Breite/Länge der CGauge schließt mit der Breite der ToolBar bzw. des Forms ab.

    Ich kann das Form auf 2 Größen verändern. Einmal Standardgröße (meine Voreinstellung) und maximiert über den gesamten Bildschirm.

    Leider macht die CGauge diese Größenveränderung nicht mit.
    Habe schon alles mit Anchors, Align und im Resize() Event von Form1 probiert.
    Leider ohne Erfolg.

    Wie bringe ich die CGauge dazu die zwei Größendarstellungen mitzumachen?

    LG
    Todd



  • Siehe dazu in der BCB Hilfe : Anchors



  • Danke für deine Antwort.

    Ich habe bereits folgende Anchors Einstellungen der CGauge getestet:

    Anchors akLEFT = true;
    Anchors akRIGHT = true;

    Aber es funktioniert nicht.

    Für jeden Weiteren Tipp vielen Dank...

    LG
    Todd



  • Todd schrieb:

    Jetzt aber eine andere Frage bezüglich dieses Themas:

    Bezüglich welchen Themas? Was hat die Ausrichtung eines Controls mit "sekundengenauer Darstellung" zu tun?

    In Zukunft bitte die Faustregel beachten: ein Thema pro Thread, ein Thread pro Thema. Danke!



  • Erstmal danke an alle die mir hier geholfen haben.

    Werde für mein CGauge Problem einen neuen Thread öffnen.

    Liebe Grüße
    Todd


Anmelden zum Antworten