TTimer: abgelaufene Zeit in Format (d:h:min:sek) anzeigen



  • ich habe einen TTimer den ich mit 2 Buttons starte und stoppe. Nun möchte ich in einem Label die abgelaufene Zeit anzeigen im Format:Tage:Stunden:Minuten:Sekunden. Zu Beginn soll alles bei 0 stehen. Wie mach ich das?

    habs mal so versucht:

    TDateTime zeit = 0;
    void __fastcall TfrmMain::Timer1Timer(TObject *Sender)
    {
        zeit = zeit + 1/(24*3600); //um eine Sekunde hochzählen
        Label1->Caption = "Prozesszeit: " + TimeToStr(zeit);
    }
    

    so funktioniert es nicht. Der Timer bleibt bei 0 stehen.



  • Wozu einen Timer? Mit dem Klick des Startbutton merkst du dir die aktuelle Zeit als Startzeit und mit dem Klick des Stopbuttons gibt du die aktuelle Zeit abzüglich der Startzeit aus. Fertich.



  • die aktuelle Zeit, seid dem der Prozess läuft, soll immer angezeigt werden. Dies soll für den Benutzer eine Statusinformation sein, damit er weiss wie lange der Prozess schon läuft.

    Edit: bin durch Deine Antwort draufgekommen:

    void __fastcall TForm1::btnStartClick(TObject *Sender)
    {
      zeitStart = Now();
      tim->Enabled = true;
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::btnStopClick(TObject *Sender)
    {
      tim->Enabled = false;
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::timTimer(TObject *Sender)
    {
      TDateTime zeitAktuell = Now();
      Label1->Caption = zeitAktuell - zeitStart;
    }
    //---------------------------------------------------------------------------
    

    Jetzt zählt er schön die Zeit hoch. Nun soll er noch nach 24 Stunden die Anzahl der Tage davorschreiben, also dd:hh:m:s(Tage:Stunden:Minuten:Sekunden)
    Dies ist erforderlich, da das Programm mehrere Tage läuft



  • was haltet ihr davon? Ich kann es leider nicht testen, da ich ja 24h warten müsste.

    TTime start;
    int tag;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      tag = 0;
      Timer1->Enabled = true;
      start = Now();
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
      if (Label1->Caption == "Prozesszeit: 0:00:00:00")
        tag++;
      String aktuell = TimeToStr(Now() - start);
      Label1->Caption = "Prozesszeit: " + IntToStr(tag) + ":" + aktuell;
    }
    


  • Nix.

    Das Ganze kann man mit einem TDateTime Objekt wesentlich eleganter lösen:
    Du initialisierts deinen Zeitstempel wie gewohnt mit Now(), bildest in der OnTimer Methode allerdings die Differenz zweier Zeitstempel:

    TDateTime Elapsed = Now() - StartTime;
    

    Ein TDateTime ist eigentlich ein double, dessen Ganzzahl Anteil die Tage angibt und der Nachkommaanteil den Bruchteil des Tages. Ein Wert von 0.5 bedeutet also 12h. Das einzige, was du noch machen musst, ist zu prüfen, ob Elapsed >= 1 ist. Wenn das der Fall ist läuft das Programm schon länger als einen Tag und du musst die abgelaufenen Tage voranstellen, ansonsten kannst du einfach die Stunden, Minuten und Sekunden ausgeben:

    Dein Ansatz hat einen Fehler: Er zählt nur den Sprung von 0 auf einen Tag, danach wird die Beschriftung nie wieder 0:00:00:00, weil Tag inzwischen 1 ist.

    if( Elapsed >= 1.0 )
    {
       Label->Caption = IntToStr( Elapsed ) + Elapsed.FormatString( ":HH:nn:ss" );
    }
    else
    {
       Label->Caption = Elapsed.FormatString( ":HH:nn:ss" );
    }
    


  • rudpower schrieb:

    Ich kann es leider nicht testen, da ich ja 24h warten müsste.

    Zum Testen statt Now() einfach einen selbst festgelegten TDateTime-Wert (siehe DocShoe) verwenden!?



  • ok, danke.

    leider erzeugt mir das Programm dabei folgenden Fehler:

    Mehrdeutigkeit zwischen '_fastcall TDateTime::operator double() const' und '_fastcall TDateTime::operator int() const'
    

    Der Fehler wird in der if-Anweisung angezeigt.

    Edit: Hab es glaub ich selbst gefunden. Hab einfach in double umgewandelt:

    void __fastcall TForm1::timTimer(TObject *Sender)
    {
      TTime elapsedTime = Time() - startTime;
    
      if (double (elapsedTime) >= 1.0)
        labTime->Caption = elapsedTime.FormatString(":hh:nn:ss");
      else
        labTime->Caption = elapsedTime.FormatString(":hh:nn:ss");
    }
    

    So dürfte es passen oder?
    Wie kann ich die Anzahl der Stunden zweistellig machen, also mit führender '0' bei einstelligen Zahlen?



  • IntToStr bietet da keine Möglichkeiten an, mit den VCL Formatierungsmöglichkeiten kenne ich mich auch nicht so gut aus. Du könntest wahlweise einen ostringstream oder eine weitere if-Anweisung benutzen, um eine Unterscheidung zu machen. Weil das hier so einfach ist würde ich eine weitere if-Anweisung benutzen:

    if( static_cast<double>( Elapsed ) < 1.0 )
    {
       Label->Caption = Elapsed.FormatString("hh:nn:ss");
    }
    else if( static_cast<double>( Elapsed ) < 10.0 )
    {
       Label->Caption = "0" + IntToStr( Elapsed ) + Elapsed.FormatString(":hh:nn:ss");
    }
    else 
    {
       Label->Caption = IntToStr( Elapsed ) + Elapsed.FormatString(":hh:nn:ss");
    }
    

Anmelden zum Antworten