Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Timer für ListBox (https://www.delphipraxis.net/194173-timer-fuer-listbox.html)

lucy 25. Okt 2017 08:23

Timer für ListBox
 
Hallo,

habe eine Listbox, die unregelmäßig Datensätze empfängt.
Jeder Datensatz sollte sich genau 5 min. in der Listbox aufhalten, bevor dieser weiter kopiert wird.

Wie könnte man so etwas umsetzen?

mkinzler 25. Okt 2017 08:24

AW: Timer für ListBox
 
Von wo empfängt die Listbox die Daten? Ich würde dort ansetzen.

bnreimer42 25. Okt 2017 08:47

AW: Timer für ListBox
 
Wie wäre es, die Infos in einem Objekt zu speichern (Text und Zeitstempel), welches an den Elementen der Listbox hängt und dann über einen Timer regelmäßig ältere Elemente zu Löschen und weiterzusenden?

Jumpy 25. Okt 2017 08:56

AW: Timer für ListBox
 
Die Daten bei Ankunft in einem Objekt speichern, das als zusätzliches Feld die Ankunftszeit haben könnte. Oder nur die Daten in das Objekt und das dann mit der Ankunftszeit in einem Record oder einem anderen Container-Objekt speichern. Keine Ahnung was da sauberer ist.

Diese Records oder Objekte dann in einem Array oder einer Liste vewalten. Die ursprüngliche Listbox sollte nur zur Anzeige der Daten, nicht deren Verwaltung dienen.

Dann könntest du mittels eines Timers alle X Sekunden überprüfen ob ein Objekt schon 5 Minuten da ist (im Vergleich zur Ankunftszeit) und dass dann weiter verarbeiten. Wenn die Datenobjekte im Array oder der Liste nach Ankunftszeit sortiert sind brauchst du jeweils auch nur die obertsen Einträge der Liste prüfen.

lucy 25. Okt 2017 09:03

AW: Timer für ListBox
 
Hallo;

folgendes zum Empfang -> "SocketClientRead" und dann schreibe ich
"ListBox1.Items.Add(msg1)" in die ListBox.

Wie überprüfe ich jeden Datensatz? Zum Beispiel mit einem Timer?
Würde dann eine Art Zeitstempel brauchen... ?

mensch72 25. Okt 2017 09:23

AW: Timer für ListBox
 
Egentlich ist es gut das es bei dir gerade noch noicht funktioniert.

Eine Listbox ist ein GUI Element, und GUI Elemente dienen neben direkten Nutzereingaben besser NUR der Anzeige von Informationen.(im Klartext: man mißbraucht GUI-Elemente nicht als Datenspeicher)
Also unterlasse es deine Socketdaten direkt in die Listbox einzufügen! (Sockets haben meist auch was mit Threads zu tun und da funktioniert dein Code dann so eh nicht mehr)

Mache dir Gedanken was du zusätzlich zu deinen Empfangsdaten alles für Informationen für deine Programmlogik brauchst.
So erstellst du einen Datenelement-Record oder eine Datenelement-Klasse. Per TLIST<DatenelementRecord> würde im Einfachsten Fall daraus eine Liste wo es dann z.B. ein "Add" schon gäbe und du mit [Index] oder "for in" durchgehen durchgehen kannst.

Der Rest (z.B. dein Timing) ist Programmlogik, erst dann kommt das Darstellen in einer GUI Listbox oder das Abspeichern in eine z.B. Datenbank.

lucy 25. Okt 2017 10:07

AW: Timer für ListBox
 
Ok,
also lieber ein Memo anlegen?
Oder ist das Memo auch nicht geeignet?

Delphi-Quellcode:
var
  Rec: CustomRec;
begin
     Socket.ReceiveBuf(Rec,SizeOf(Rec));
     Memo1.Lines.Add(rec.Text)+(Zeitstempel);
end;
Wie würde die Überprüfung im Memo ablaufen? (Timer)

Delphi-Quellcode:
begin
 if Memo1. ...... then
  begin

  end;
end;

hoika 25. Okt 2017 10:30

AW: Timer für ListBox
 
Hallo,
erzeuge eine Klasse mit den gewünschten Daten

type
TListBoxEintrag = class
AnzeigeText: String;
Zeit: TDateTime;
end;

Erzeuge beim Eintreffen neuer Einträge neue Objekte und speichere sie in einer TObjectList.

Diese Objekt-Liste wird per Timer "bereinigt" (alte Elemente > x Minuten) fliegen raus.
Danach wird die ListBox neu gefüllt.

lucy 25. Okt 2017 10:49

AW: Timer für ListBox
 
Es sollen aber nicht alle Daten rausfliegen!
Nur der Datensatz, der seit fünf Minuten vorhanden ist.

p80286 25. Okt 2017 11:08

AW: Timer für ListBox
 
Zitat:

Zitat von lucy (Beitrag 1384095)
Es sollen aber nicht alle Daten rausfliegen!
Nur der Datensatz, der seit fünf Minuten vorhanden ist.

Wenn ich das von Hand machen müßte, dann würde einen Stapel erstellen
:Hole_Nachricht
auf den ich die eingehenden Nachrichten lege.
Dann würde ich mir die unterste anschauen ob die schon 5 Minuten im Stapel ist. Wenn ja wird sie herausgenommen. Das mache ich so lange bis die unterste Nachricht weniger als 5 Minuten im Stapel liegt.
goto Hole_Nachricht

so ungefähr

Gruß
K-H

vergessen:
Zwischendurch muß ich natürlich den Inhalt des Stapels anzeigen (lassen).

Sherlock 25. Okt 2017 13:03

AW: Timer für ListBox
 
Zitat:

Zitat von p80286 (Beitrag 1384101)
goto Hole_Nachricht

WARUM??!

@Lucy: Vergiss goto, google es nicht und verankere in Deinem Hirn, daß goto ganz bestimmt nicht in Delphi existiert.

Sherlock

jaenicke 25. Okt 2017 13:34

AW: Timer für ListBox
 
Wir machen das sehr einfach:
Wir nehmen eine TVirtualStringTree, die in OnGetText auf die Daten in einer Liste zugreift. Ein Timer (bzw. bei uns ein Thread, aber das ist ja egal) stößt dann das Aufräumen der Liste an, setzt ggf. die Anzahl der Elemente in der Liste neu bzw. ruft Invalidate auf. Daraufhin werden die dann aktuellen Elemente in der Liste gezeichnet.

p80286 25. Okt 2017 13:50

AW: Timer für ListBox
 
Zitat:

Zitat von Sherlock (Beitrag 1384117)
Zitat:

Zitat von p80286 (Beitrag 1384101)
goto Hole_Nachricht

WARUM??!

Damit Du in einer Schleife bist!?

Ach Du störst Dich an dem GOTO ?
Na dann nimmt man halt
Delphi-Quellcode:
While not..... begin ... end
oder
Delphi-Quellcode:
repeat ....until
...

ich wäre nie auf den Gedanken gekommen, daß man das als Delphi-Code mißverstehen könnte.

Gruß
K-H

Aviator 25. Okt 2017 13:58

AW: Timer für ListBox
 
Zitat:

Zitat von jaenicke (Beitrag 1384120)
Wir machen das sehr einfach:
Wir nehmen eine TVirtualStringTree, die in OnGetText auf die Daten in einer Liste zugreift. Ein Timer (bzw. bei uns ein Thread, aber das ist ja egal) stößt dann das Aufräumen der Liste an, setzt ggf. die Anzahl der Elemente in der Liste neu bzw. ruft Invalidate auf. Daraufhin werden die dann aktuellen Elemente in der Liste gezeichnet.

Ich glaube ein VirtualStringTree wäre in der Angelegenheit etwas overkill. Ich gehe mal davon aus, dass der TE gerade erst mit dem Programmieren angefangen hat und der VST dann "etwas" zu kompliziert wäre.

Aber trotzdem sollte er die Daten in einer Klasse ablegen. Die Instanz der Klasse sollte, wie auch schon des öfteren erwähnt, in einer ObjectList abgespeichert werden. Danach ist es ein Leichtes, die Liste (von oben nach unten) zu durchlaufen und dann die Einträge, die älter sind als 5 Minuten, aus der Liste zu entfernen. Schlussendlich müssten dann nur noch die Elemente in der ListBox neu erstellt/gezeichnet werden.

@TE: Was hast du denn bereits von den Vorschlägen umgesetzt? Oder wo hängst du gerade :?:

jaenicke 25. Okt 2017 15:53

AW: Timer für ListBox
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Aviator (Beitrag 1384124)
Ich glaube ein VirtualStringTree wäre in der Angelegenheit etwas overkill. Ich gehe mal davon aus, dass der TE gerade erst mit dem Programmieren angefangen hat und der VST dann "etwas" zu kompliziert wäre.

Ich finde das nicht. Ich habe ja nun schon einigen geholfen beim Lernen und so kompliziert ist der VST nicht, wenn man den für einfache Zwecke benutzt. Klar, man kann damit auch deutlich kompliziertere Sachen machen. Aber nur die Anzahl der Einträge setzen und OnGetText implementieren... das ist nicht komplizierter als in einer anderen Liste die Einträge zu löschen und neu hinzuzufügen.

Komplettes Beispiel (Projekt liegt im Anhang):
Delphi-Quellcode:
unit VstDemo;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  VirtualTrees, System.Generics.Collections, System.DateUtils;

type
  TMyData = class
  private
    FCreationTime: TDateTime;
  public
    constructor Create(const ATime: TDateTime);
    property CreationTime: TDateTime read FCreationTime write FCreationTime;
  end;

  TfrmVstDemo = class(TForm)
    vstEntries: TVirtualStringTree;
    btnAdd: TButton;
    tmrDelete: TTimer;
    procedure btnAddClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure vstEntriesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
      var CellText: string);
    procedure tmrDeleteTimer(Sender: TObject);
  private
    FEntries: TList<TMyData>;
    procedure UpdateTree;
  public
  end;

var
  frmVstDemo: TfrmVstDemo;

implementation

{$R *.dfm}

{ TfrmVstDemo }

procedure TfrmVstDemo.btnAddClick(Sender: TObject);
begin
  // Eintrag hinzufügen
  FEntries.Add(TMyData.Create(Now));
  UpdateTree;
end;

procedure TfrmVstDemo.FormCreate(Sender: TObject);
begin
  // Liste erzeugen
  FEntries := TObjectList<TMyData>.Create;
end;

procedure TfrmVstDemo.FormDestroy(Sender: TObject);
begin
  // Liste freigeben
  FEntries.Free;
end;

procedure TfrmVstDemo.tmrDeleteTimer(Sender: TObject);
var
  i: Integer;
begin
  // Alle Einträge durchgehen und nach 5 Sekunden herauswerfen
  for i := FEntries.Count - 1 downto 0 do
    if SecondsBetween(FEntries[i].CreationTime, Now) >= 5 then
      FEntries.Delete(i);
  // Baumanzeige aktualisieren
  UpdateTree;
end;

procedure TfrmVstDemo.UpdateTree;
begin
  // Anzahl der Einträge setzen und Anzeige aktualisieren
  vstEntries.ChildCount[vstEntries.RootNode] := FEntries.Count;
  vstEntries.Invalidate;
end;

procedure TfrmVstDemo.vstEntriesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: string);
begin
  // Text, der für den Eintrag angezeigt werden soll, liefern indem man diesen in CellText schreibt
  CellText := 'Eintrag von ' + DateTimeToStr(FEntries[Node.Index].CreationTime);
end;

{ TMyData }

constructor TMyData.Create(const ATime: TDateTime);
begin
  FCreationTime := ATime;
end;

end.

Aviator 25. Okt 2017 15:59

AW: Timer für ListBox
 
Zitat:

Zitat von jaenicke (Beitrag 1384136)
Zitat:

Zitat von Aviator (Beitrag 1384124)
Ich glaube ein VirtualStringTree wäre in der Angelegenheit etwas overkill. Ich gehe mal davon aus, dass der TE gerade erst mit dem Programmieren angefangen hat und der VST dann "etwas" zu kompliziert wäre.

Ich finde das nicht. Ich habe ja nun schon einigen geholfen beim Lernen und so kompliziert ist der VST nicht, wenn man den für einfache Zwecke benutzt. Klar, man kann damit auch deutlich kompliziertere Sachen machen. Aber nur die Anzahl der Einträge setzen und OnGetText implementieren... das ist nicht komplizierter als in einer anderen Liste die Einträge zu löschen und neu hinzuzufügen.

Das ist wohl richtig. Man kann den auch sehr abgespeckt benutzen und ist dann in einem späteren Stadium flexibel. Ich selbst arbeite ja fast ausschließlich mit dem VST wenn es um irgendeine Listendarstellung geht.

Nur würde ich sagen, dass der TE noch ein grundsätzliches (Verständnis)Problem hat. Aber das kann auch nur er selbst erläutern. Eventuell wird es ja durch dein Beispiel etwas deutlicher was wir die ganze Zeit versuchen zu erklären.

lucy 25. Okt 2017 23:53

AW: Timer für ListBox
 
Hallo,

vielen Dank für die ganzen Beiträge. Muss erstmal alles sortieren und ausprobieren.
Danke :-)

Habe mich für ein StringGrid entschieden, und teste noch ein wenig rum.


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