Card im Hintergrund / Timer im NumberFormat „00“

Startseite Foren Deutsches LiveCode-Forum Card im Hintergrund / Timer im NumberFormat „00“

Schlagwörter: , , ,

Ansicht von 4 Antwort-Themen
  • Autor
    Beiträge
    • #26028
      Aldred
      Teilnehmer

        Hallo ihr Lieben und einen wunderschönen Samstag!

        Heute beehre ich euch mit zwei Fragen:

        1. Card im Hintergrund laufen lassen:

        Ich habe in meinem Substack 4 Cards die ich über eine NavBar ansteuern kann. Auf Card 1 kann ich einen Timer ablaufen lassen der natürlich weiterlaufen sollte, selbst wenn ich die Cards wechsle.
        Der Timer-Handler holt sich die aktuelle TimerZeit aus dem dafür vorgesehenen Field, bearbeitet sie (+ 1 Sekunde) und schreibt die neue Timer-Zeit wieder in selbiges Feld zurück.

        Wenn ich nun die Cards wechsle, kommt die Fehlermeldung, dass es dieses Timer-Feld nicht mehr gibt. Was ich auch verstehen kann, da die Card ja nicht mehr geöffnet ist.
        Gibt es eine Möglichkeit die Card im Hintergrund offen zu lassen, so dass der Handler in Ruhe weiter „Timen“ kann?

        2. Timer im NumberFormat „00“
        Jener oben beschriebene Timer funktioniert erstmal einwandfrei.

        
        on startArbeitsTimer
           
           put the text of fld "fStdHeute" of cd "Start" into tStd
           put the text of fld "fMinHeute" of cd "Start" into tMin
           put the text of fld "fSecHeute" of cd "Start" into tSec
           put tStd &":"& tMin &":"& tSec into tZeit
           convert tZeit to seconds
           subtract 1 of tZeit
           convert tZeit to dateItems
           set the numberFormat to "00"
           put item 4 of tZeit into tStdNeu
           put item 5 of tZeit into tMinNeu
           put item 6 of tZeit into tSecNeu
           set the text of fld "fStdHeute" to tStdNeu
           set the text of fld "fMinHeute" to tMinNeu
           set the text of fld "fSecHeute" to tSecNeu
           send startArbeitsTimer to me in 1000 milliseconds
           
           if tStdNeu = 0 and tMinNeu = 0 and tSecNeu = 0 then
              set the text of fld "fStdHeute" of cd "Start" to tStdNeu
              set the text of fld "fMinHeute" of cd "Start" to tMinNeu
              set the text of fld "fSecHeute" of cd "Start" to tSecNeu
              stopArbeitsTimer
              set the visible of grp "group_US" of cd "Start" to true
              startUberstundenTimer
              
           end if
           
        end startArbeitsTimer

        Problem ist folgendes: sobald die Zahl einstellig wird, wird auch nur eine Stelle angezeigt. Trotz numberFormat „00“
        Setze ich die zusätzliche 0 per Script ein, nimmt er diese zwei Zahlen bei der nächsten Timer-Runde wieder aus dem Field und es geht nicht weiter.

        So… What to do? 🙂

        Liebe Grüße
        Aldred

      • #26033
        Klaus Major
        Administrator

          Hi Aldred,

          1.

          Gibt es eine Möglichkeit die Card im Hintergrund offen zu lassen

          nein, gibt es natürlich nicht.
          Aber wie bei der Post (nur viel besser) kommt mit der richtigen Adresse alles korrekt beim Empfänger an!
          Schau Dir diese zwei Zeilen aus dem Skript an und finde den Unterschied:

          put the text of fld "fStdHeute" of cd "Start" into tStd
          ...
          set the text of fld "fStdHeute" to tStdNeu

          Capisce?
          Füge -> of cd „Start“
          hinzu und das wars! 🙂

          2. numberformat
          Das setzen von NUMBERFORMAT beeiinflusst nur alle nachfolgenden mathematischen Operationen.
          Diese können (und müssen) wir hier simulieren.
          Beispiel:

          set the numberformat to "00"
          put 1
          ## -> 1
          ## ABER hier der Trick:
          put 1 + 0
          ## -> 01
          ## Bescheuert, aber funktioniert! :-D

          Allerdings benötigen wir hier gar nicht NUMBERFORMAT, da LC SEHR gut mit Datum und Zeit rechnen kann!

          on startArbeitsTimer
             
             ## Wir benötigen eigentlich keine extra Variablen hierfür
             put the text of fld "fStdHeute" of cd "Start" & ":" & the text of fld "fMinHeute" of cd "Start" & ":" & the text of fld "fSecHeute" of cd "Start" into tSec
             
             ## LC denkt englisch, also ist 14:00 Uhr für LC 
             ## -> 2:00 PM
             ## Das wollen wir nicht, daher:
             set the twelvehourtime to FALSE
             convert tZeit to seconds
             subtract 1 of tZeit
             
             ## Hier der Trick OHNE numberformat:
             convert tZeit to LONG TIME
             ## Das ergibt die neue Zeit im gewünschten Format!
             ## -> 13:07:11
             ## dateitems wären etwas OVERKILL in diesem Fall
                
             set itemdel to ":"
             set the text of fld "fStdHeute" OF CD "Start" to item 1 of tZeit
             set the text of fld "fMinHeute" OF CD "Start" to item 2 of tZeit
             set the text of fld "fSecHeute" OF CD "Start" to item 3 of tZeit   
             ## Das deckt ja auch 0 ab, was Du aber explizit im IF Fall noch einmal gemacht hast.
             
             ## Ge-SEND-ete Messages immer in Anführungszeichen!
             send "startArbeitsTimer" to me in 1000 milliseconds
             
             if tZeit = "00:00:00" then
                stopArbeitsTimer
                set the visible of grp "group_US" of cd "Start" to true
                startUberstundenTimer
             end if   
          end startArbeitsTimer

          Gruß

          Klaus

        • #26034
          Klaus Major
          Administrator

            Bin mir allerdings nicht sicher, ob es so richtig(er) wäre:

               set the text of fld "fSecHeute" OF CD "Start" to item 3 of tZeit   
               ## Das deckt ja auch 0 ab, was Du aber explizit im IF Fall noch einmal gemacht hast. 
               
               if tZeit = "00:00:00" then
                  stopArbeitsTimer
                  set the visible of grp "group_US" of cd "Start" to true
                  startUberstundenTimer
            
                  ## Der "ArbeitsTimer" hat ja jetzt seine Schuldigkeit getan, oder?
                  ## Daher packen wir das in einen ELSE Fall
                else
                 ## Ge-SEND-ete Messages immer in Anführungszeichen!
                 send "startArbeitsTimer" to me in 1000 milliseconds
               end if   
            end startArbeitsTimer
          • #26055
            Axwald
            Teilnehmer

              Hallo,

              Der Timer-Handler holt sich die aktuelle TimerZeit aus dem dafür vorgesehenen Field, bearbeitet sie (+ 1 Sekunde) und schreibt die neue Timer-Zeit wieder in selbiges Feld zurück.

              Umständlich (und vermutlich recht ungenau). Besser einfach den Computer-Timer nutzen, über „the seconds“. Beispiel unten.

              „numberFormat“:
              Fehlerträchtig! Klaus hat erklärt, warum. „format()“ hat zwar eine ekelhafte Syntax, arbeitet aber zuverlässig: format(„%02s“, myMinute) gibt immer einen 2-stelligen Wert.


              Mein Beispiel zu diesem Problem:

              Ich merke mir die Start-Zeit (als „the seconds“) in einer globalen Variable, und setze ein Skript als „Timer-Schleife“ ein, das sich immer wieder selbst aufruft. Die abgelaufene Zeit addiere ich mir nicht zusammen, sondern errechne sie jeweils aus der Differenz „Start-Sekunden“ zu „aktuelle Sekunden“.
              Das Berechnen & Formattieren der abgelaufenen Zeit übernimmt eine eigene Funktion („secsToTime(10000)“ => „02:46:40“).

              Mein „Start“-Button:

              global gStartTime
              on mouseUp
                 put the seconds into gStartTime          --  Zeit merken
                 ourTimer                                 --  Timer-Schleife starten
              end mouseUp

              Die Timer-Schleife „ourTimer“ läuft im Stack-Script:

              global gStartTime
              on ourTimer what
                 switch what
                    case "stop"                                --  Timer stoppen, Ergebnis anzeigen:
                       put secsToTime(the seconds - gStartTime) into theTime     --  Ergebnis merken
                       put theTime into fld "time_fld" of cd "time_cd" of this stack    --  anzeigen
                       repeat for each line L in the pendingMessages       --  Message-Queue stoppen
                          if "ourTimer" is in L then cancel item 1 of L
                       end repeat
                       answer "Zeit gesamt: " & theTime                     --  offizielle Zeitnahme
                       put empty into gStartTime                             --  System zurücksetzen
                       put empty into fld "time_fld" of cd "time_cd" of this stack
                       break
                    default                            --  der normale Ablauf während der Zeitnahme:
                       put secsToTime(the seconds - gStartTime) into \
                             fld "time_fld" of cd "time_cd" of this stack          --  Zeit anzeigen
                       send "ourTimer" to me in 1 seconds         --  und dieses Skript wieder rufen
                 end switch
              end ourTimer

              Normal aufgerufen (ohne „Stop“ als Parameter) schreibt dies die vergangene Zeit in das dafür vorgesehene Feld (wir müssen dazu nicht auf der Karte sein!). Anschließend startet sich das Skript nach 1 Sekunde selber wieder.

              Mit „Stop“ wird es etwas komplizierter:
              Wir merken uns die vergangene Zeit, entfernen in der Repeat-Schleife etwaige weitere Aufrufe von „OurTimer“ aus den wartenden Messages (um das Skript zu stoppen), geben das Ergebnis bekannt und setzen das Zeit-Feld & die globale Variable zurück.

              Nun die Funktion, die aus „the seconds“ etwas Verständliches macht (im Stack-Script):

              function secsToTime theSecs
                 put theSecs div 86400 into myDay                   --  erst ganze Tage 'rausrechnen
                 put theSecs - (myDay * 86400) into theSecs
                 put theSecs div 3600 into myHour                --  dann ganze Stunden 'rausrechnen
                 put theSecs - (myHour * 3600) into theSecs
                 put theSecs div 60 into myMinute                --  dann ganze Minuten 'rausrechnen
                 put theSecs - (myMinute * 60) into theSecs           --  der Rest sind die Sekunden
                 if myDay > 0 then                                     --  Formatieren & zurückgeben
                    return myDay & " T, " & format("%02s", myHour) & ":" & \
                          format("%02s", myMinute) & ":" & format("%02s", theSecs)
                 else
                    return format("%02s", myHour) & ":" & \
                          format("%02s", myMinute) & ":" & format("%02s", theSecs)
                 end if
              end secsToTime

              „div“ wird benutzt um herauszufinden, wieviele ganze Tage (Stunden, Minuten) in „theSecs“ enthalten sind, gemerkt & abgezogen. Das Ergebnis wird formattiert & zurückgegeben.

              Fehlt noch der „Stop“-Button:

              on mouseUp
                 ourTimer "stop"
              end mouseUp

              Gar nicht so kompliziert, oder?

              Viel Spaß!

              Code mit Community Version erstellt, also GPL V3. Enthält keine plattform- oder versionsspezifischen Funktionen, sollte also überall laufen.

            • #26078
              Aldred
              Teilnehmer

                Hi Klaus und Axwald,
                Danke für eure Antworten und Erklärungen.
                Klaus, ich habs mit deiner Methode umgebaut und es läuft perfekt (Ich hab keine Sekunde daran gezweifelt 🙂 )
                Herzlichen Dank dafür.
                Und Axwald, danke für deine Erklärung. Es ist immer gut dazu zu lernen!

                Liebe Grüße
                Aldred

            Ansicht von 4 Antwort-Themen
            • Du musst angemeldet sein, um auf dieses Thema antworten zu können.