dynamische Label



  • P.S: Entsprechend also ist der Ansatz mit dem Timer hier sicher nicht der dümmste. Die Version mit dem Sleep halte ich für etwas gewagt, da sie tatsächlich den ganzen Applikationsthread und damit die Verarbeitung der Nachrichtenschleife blockiert für 200ms. Ausser natürlich man verwendet eine Schleife mit dem Inhalt Sleep(1) und Application->ProcessMessages(). Das wiederum ist aber eine massiv ungenauere und umständlichere Variante als sie eigentlich nötig wäre. Denn genau für solche Fälle stellt Windows ja TimerCallbacks zur Verfügung.



  • Ich kann Webfritzi nur zustimmen. Unter den gegebenen Umständen ist der Einsatz eines Timers absolut sinnlos. Wo soll denn da der Vorteil gegenüber einem direkten Schreiben in das Label sein? Im Gegenteil, es ist ungünstiger, weil es mehr Ressourcen verbraucht.



  • also ich lass das erstmal so,
    wie ich das gemacht habe,
    es funktioniert und ich zeige halt nur das wichtigste an.

    den Rest lass ich halt loggen.
    trotzdem Danke für eure Antworten.



  • Joe_M. schrieb:

    Ich kann Webfritzi nur zustimmen. Unter den gegebenen Umständen ist der Einsatz eines Timers absolut sinnlos. Wo soll denn da der Vorteil gegenüber einem direkten Schreiben in das Label sein? Im Gegenteil, es ist ungünstiger, weil es mehr Ressourcen verbraucht.

    Du Widersprichst dir immer wieder selber hier.
    Das mit dem Timer verbraucht absolut nicht mehr Resourcen.
    Das Blockieren der Anwendung ist allerdings wie schon gesagt als absolut sinnlos zu betrachten.
    Also mit dem Timer ist dies der beste Ansatz, da es ihm nicht darauf ankommt, ob ältere Meldungen in der Anzeige unterschlagen werden ...



  • Ich widerspreche mir nicht, sondern versuche den Lösungsweg an neue Informationen anzupassen.

    Probier Deine Timerlösung doch einfach mal selbst aus. Und zwar nicht mit Buttons sondern in einer Schleife. Du wirst sehr schnell merken, dass dieser Lösungsweg nicht gangbar ist. Was glaubst Du denn, wie oft der Timer aufgerufen wird, wenn die Anwendung ausgelastet ist? Ich kann Dir die Antwort auch direkt geben: Gar nicht! Zumindest solange nicht, wie Du aus der Schleife heraus nicht Application->ProsessMessages() aufrufst. Und dann kannst Du dir den ganzen Firlefanz mit dem Timer auch direkt sparen und das Label vor dem Application->ProcessMesssages() setzen.



  • Joe_M. schrieb:

    Was glaubst Du denn, wie oft der Timer aufgerufen wird, wenn die Anwendung ausgelastet ist?

    Innerhalb eines gewissen Zeitrahmens nach dem Ablauf des Intervalls. Alles andere sind höchstens schlechte/fehlerhafte Applikationsdesigns.

    Joe_M. schrieb:

    Wo soll denn da der Vorteil gegenüber einem direkten Schreiben in das Label sein? Im Gegenteil, es ist ungünstiger, weil es mehr Ressourcen verbraucht.

    Das ist nicht richtig. Das direkte Schreiben ins Label hat mehrere Nachteile. Folgendes hängt an jedem neuen Setzen der Caption mit dran:
    Schreiben des Labels
    Neu zeichnen des Forms oder des Form-Bereichs

    Was passiert jetzt bei einer hohen Schreibkadenz? Dein Rechner wird nur damit beschäftigt sein, das Label zu zeichnen und klaut dir damit Rechenzeit (ebenfalls eine Ressource) für sinnvollere Anwendungen. Ausserdem ist es doch verschwendung etwas zu zeichnen, das sowieso nicht gelesen werden kann? (Stichwort Updaterate, hatte ich vorher schon erwähnt).

    Joe_M. schrieb:

    Ich kann Dir die Antwort auch direkt geben: Gar nicht! Zumindest solange nicht, wie Du aus der Schleife heraus nicht Application->ProsessMessages() aufrufst.

    Weshalb man ja auf intensive Schleiferei innerhalb eines Eventhandlers wie z.B. ButtonClick verzichten, und derlei Operationen in weitere Threads auslagern sollte...

    Joe_M. schrieb:

    Und dann kannst Du dir den ganzen Firlefanz mit dem Timer auch direkt sparen und das Label vor dem Application->ProcessMesssages() setzen.

    Nö. Viel besser wäre es den Applikations"design" zu kippen und über was brauchbares wie MVC oder Document/View nachzudenken.



  • Also: Sleep() ist Quatsch und alles reinschreiben ins Label ist Quatsch, da zu schnell, um es zu lesen. Ich denke, da sind wir uns alle einig. Ein Timer ist aber auch Quatsch. Ich habe das doch schon erläutert. Ihr lest meine Beiträge einfach nicht richtig. Das Label soll doch sowas wie eine Status-Information sein. Wenn man ein Label verwendet, werden aber öfter Stati angezeigt werden, die schon lange nicht mehr aktuell sind:

    - Wichtiges Ereignis ist da (sollte eigentlich genau jetzt angezeigt werden)
    - Timer wartet ein paar Sekunden
    - Ereignis wird angezeigt, allerdings viel zu spät

    Wie gesagt: damit wird der User belogen, weil die Aktion, welche angezeigt wird, weder momentan in Gange ist noch gerade eben beendet worden ist.



  • Wie gesagt: damit wird der User belogen, weil die Aktion, welche angezeigt wird, weder momentan in Gange ist noch gerade eben beendet worden ist.

    Was wie hier schon 1000mal erläutert wurde, hier nicht von Relevanz ist ... 🙄



  • WebFritzi schrieb:

    - Wichtiges Ereignis ist da (sollte eigentlich genau jetzt angezeigt werden)
    - Timer wartet ein paar Sekunden
    - Ereignis wird angezeigt, allerdings viel zu spät

    Ganz offensichtlich ist der, der sich beschwert, dass seine Beiträge nicht gelesen werden, selber einer, der Beiträge nicht (richtig) liest. Erlaube mir, deine Einwände zu kommentieren:

    WebFritzi schrieb:

    - Timer wartet ein paar Sekunden

    UnEinloggbar schrieb:

    Wer sagt denn bitte, dass der Timer 1-2 Sekunden Intervalle fahren soll? Ausserdem ist erfahrungsgemäss alles was eine schnellere Änderungsrate hat als 2Hz (0.5s Pause) unleserlich für den Benutzer und damit ohnehin uninteressant...

    WebFritzi schrieb:

    - Ereignis wird angezeigt, allerdings viel zu spät

    Falsch. Du überschreibst ja den Status immer mit dem jüngsten status. Ereignisse die also "kurz" auftreten, werden gar nicht angezeigt. Nutzt auch nichts, etwas anzuzeigen, ohne dass der User die Zeit hat, es zu lesen. Und wenn der Status mit mehr als 2Hz wechselt, würde ich mich sowieso fragen ob da nicht was anderes falsch ist.



  • Entschuldige, aber du drückst dich so unklar aus, dass das, was du willst, unverständlich ist. Ich habe immer noch keinen blassen Schimmer, was hier ein Timer soll. Erkläre doch bitte nochmal ganz genau, wie das laufen sollte. Danke.



  • WebFritzi schrieb:

    Entschuldige, aber du drückst dich so unklar aus, dass das, was du willst, unverständlich ist. Ich habe immer noch keinen blassen Schimmer, was hier ein Timer soll. Erkläre doch bitte nochmal ganz genau, wie das laufen sollte. Danke.

    *ROFL* 🙄



  • Also nochmals zum mitzeichnen für Analphabeten:

    Ich habe ein Element welches mir den momentanen Status speichert. Der Einfachheithalber sei das eine Variable FStatus des Typs AnsiString der Formularklasse. In diese Variable wird über ZUgriffsfunktionen von diversen Quellen der Status der Applikation geschrieben. Kommt die Applikation in einen neuen Status, wird der alte überschrieben.

    Nun schreit der Schlaue webfritzi aber: Speicherverschwendung! Da kann ich ja grad so gut direkt in die Caption des anzeigenden Labels schreiben. Grundsätzlich hat er auch recht. Die Frage ist allerdings, was die Konsequenz eines Statuslabel->Caption = "neuer Status" ist: In diesem Fall wäre es zum Einen das Überschreiben der Variabel, sowie das anschliessende, rechenaufwendige neuzeichnen des Labels, wenn nicht sogar des ganzen Formulars.

    Dazu kommt, dass bei zu häufigem Statuswechsel (ich sagte ja >2 Hz oder anders ausgedrückt häufiger als alle 500ms) der Benutzer das angezeigte sowieso nicht lesen kann, daher also auch die Anzeige nonsens ist. Aus diesem Grund kann man also auch das Zeichnen des Formulars auf 2Hz (oder eben den Intervall von 500ms) beschränken.

    Wozu nun also der Timer? Ganz einfach: In der Timer-Intervall-Routine steht nichts weiter als Statuslabel->Caption = FStatus. Dies führt dazu, dass das Formular nur alle 500ms damit b elästigt wird, sich neu zu zeichnen und ich mir die sonstigen unnötigen Rechenzyklen erspare.

    War das jetzt verständlicher?



  • Du übersiehst nur eine Kleinigkeit: Ohne von Zeit zu Zeit ein Application->ProcessMessages() einzufügen, wird nur eine einzige 'Nachricht' angezeigt. Nämlich die allerletzte und das auch erst, sobald die App. in den Idle Modus geht. Warum sollte ich also einen Timer einsetzen, wenn ich doch sowieso manuell das Neuzeichen anfordern muß (mit ProcessMessages(), falls Du es schon wieder vergessen hast). Wie oft ich in ein Label schreibe ist dabei absolut irrelevant. Erst beim Aufruf von Application->ProcessMessages, oder wenn die Anwendung nicht mehr ausgelastet ist, wird neu gezechnet.

    Und genau deshalb ist der Einsatz eines Timers Ressourcenverschwendung (!= Speicherverschwendung) und in diesem Fall absolut sinnlos. Timer stehen unter Windows nur in begrenzter Anzahl zur Verfügung, also sollte man sie nur einsetzen, wenn man sie wirklich braucht.

    Joe_M.



  • Wie wäre es mit sehr wohl einem Timer, der mit Interval auf 1 Sek. gestellt wird oder wie lange es halt gewünscht ist, und du in der Timerfunktion den Timer wieder auf Enabled=false setzt, die Nachricht leerst usw.?

    Also kurzer Code, zusammengefasst:

    if(Timer1->Enabled)
    {
        Timer1->Enabled=false;
        // Sollte der Timer noch eingeschaltet sein, also Nachrichten "zu schnell" erscheinen
    }
    Timer1->Enabled=true;
    Label1->Caption=message;
    

    Und im OnTimer:

    Timer1->Enabled=false;
    Label1->Caption="";
    

    Also dass der Timer hier als "Verzögerer" eingesetzt wird, und sich nur einmal aufruft. Ist vielleicht mit Kanonen auf Fliegen geschossen, jedoch wohl hierbei und mit dem BCB die einfachste Variante, wenn man kein sleep() verwenden möchte... so finde ich jedenfalls. 😉



  • Manchmal fühle ich mich sooo müde...

    Ich gebs auf.

    Joe_M.



  • Nimm doch Sleep, wie bereits erwähnt, aber verarbeite die Labels in einem Thread, so kann das Programm weiterlaufen, während der Thread die Zwangspause einlegt. Also ich find da ist akualität vorhanden.



  • 😃

    Manchmal fühle ich mich sooo müde...

    😃



  • Christian2111 schrieb:

    😃

    Manchmal fühle ich mich sooo müde...

    😃

    Ja, das ist nunmal so, wenn man denn Sinn für die einfachsten und sinnvollsten Lösungsansätze verloren hat ....



  • zufaulzumeinloggen schrieb:

    Du übersiehst nur eine Kleinigkeit: Ohne von Zeit zu Zeit ein Application->ProcessMessages() einzufügen, wird nur eine einzige 'Nachricht' angezeigt.

    Wieso sollte dem so sein? Wenns ist, weil irgendwo in nem Button-Click ne Schleife abläuft, dann habe ich dazu bereits Stellung bezogen:

    UnEinloggbar schrieb:

    Joe_M. schrieb:

    Ich kann Dir die Antwort auch direkt geben: Gar nicht! Zumindest solange nicht, wie Du aus der Schleife heraus nicht Application->ProsessMessages() aufrufst.

    Weshalb man ja auf intensive Schleiferei innerhalb eines Eventhandlers wie z.B. ButtonClick verzichten, und derlei Operationen in weitere Threads auslagern sollte...

    Application->ProcessMessages ist ja das was immer, ganz ohne dein Zutun, läuft wenn nicht grade ne Nachricht bearbeitet wird. Das ist ja der Witz daran. Alles und jedes (auch jeder ButtonClick) ist nichts weiter als eine von ProcessMessages() verarbeitete Nachricht. Kannst du auch ganz einfach testen: Mach nen Button der nur

    while(true)
    {
        Application->ProcessMessages();
        Sleep(1);
    }
    

    ausführt. Dazu ein anderer in dessen Eventhandler du nen Breakpoint setzt. Nun klickst du erst auf den ersten Button, dann auf den zweiten. Wenn die Applikation dann anhält, wirst du feststellen, dass im Callingstack zwei mal Application->ProcessMessages() aufgeführt wurde. Der tiefer liegende Aufruf hat die erste Eventhandler-Routine aufgerufen, die höher liegende die zweite mit dem Breakpoint. Das Spiel lässt sich so beliebig fortsetzen.

    @Sphy: DAS wiederum ist nun wirklich unsinnig!



  • 👍


Anmelden zum Antworten