AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi ListView: Wie erkennt man, dass Elemente fertig eingetragen?
Thema durchsuchen
Ansicht
Themen-Optionen

ListView: Wie erkennt man, dass Elemente fertig eingetragen?

Ein Thema von stephan007 · begonnen am 3. Mai 2007 · letzter Beitrag vom 4. Mai 2007
Antwort Antwort
stephan007

Registriert seit: 2. Mär 2007
48 Beiträge
 
#1

ListView: Wie erkennt man, dass Elemente fertig eingetragen?

  Alt 3. Mai 2007, 00:31
Hallo!

Wir haben folgendes Problem:

Wir tragen in die ListView Ergebnisse aus einem Ethernet Scan ein. Wissen daher nicht wirklich, wann die Antworten kommen. Haben daher das ganze mit einem Timer gelöst, der die folgende Aktion nach 500 ms nach dem letzten Eintrag ausführen soll (Timestamp bei Schreibebeginn und timesince).

Wenn die Einträge in der Liste drinnen sind und nach 500 ms nichts neues mehr kommt (also der Timer nicht mehr auslöst), dann wollen wir die Spalten (Columns) auf die optimale Breite setzen (sprich den Text in den jeweiligen Columns hinsichtlich ihrer Länge analysieren und daraus die rrichtige Spaötembreite ermitteln.). Das funktioniert, detto, dass wir Spalten ohne Einträge auf 0 setzen (also ausblenden).

Nun haben wir aber das Problem, dass wir einen Indexüberlauf bekommen. Beim Debugen sehen wir, dass die zu behandelnde Spalte einen Index um 1 größer hat, als gerade verfügbar ist. Insgesamt haben wir 15 Spalten, die erste ist die Caption und dann (über die Subitems) von 0 bis 14. Nun kanns mir aber passieren, dass ich bei Subitem(12) eine Exception wegen Indexüberlauf bekomme. Soll heißen, dass wir davon überzeugt sind, dass das Schreiben scheinbar doch noch nicht fertig war.

Daran knüpft nun meine Frage an:
Gibt es in Delphi eine Möglichkeit festzustellen, ob noch auf eine ListView geschrieben wird respektive ob das Schreiben schon fertig ist (sowas wie ein Event "Drawfinished" - in die ListView schreiben ist ja eigentlich auch nichts anderes als ein Draw Event (wird einem erst beim Umfärben einzelner Einträge bewußt). Ich muss also scheinbar erst schauen, ob auch wirklich fertig eingetragen wurde. Denn sonst ändert sich der Index während der Bearbeitung und Delphi meckert daw an.

Ich suche also ein Event oder eine Funktion, an Hand der ich erkenne, dass die ListView fertig geschrieben ist und ich mit meinem Sizer drüber kann, ohne einen Indexüberlauf auf Grund noch fehlender Spalten zu riskieren. Wenn jemand von Euch hierzu hilfreiche Tipps hätte, wäre mir sehr geholfen.

Danke schon im Voraus!
Lg,
Stephan.
  Mit Zitat antworten Zitat
Benutzerbild von chaosben
chaosben

Registriert seit: 27. Apr 2005
Ort: Görlitz
1.358 Beiträge
 
Delphi XE2 Professional
 
#2

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 3. Mai 2007, 06:31
Hi Stephan!

Zitat von stephan007:
Ich muss also scheinbar erst schauen, ob auch wirklich fertig eingetragen wurde. Denn sonst ändert sich der Index während der Bearbeitung und Delphi meckert daw an.
Ich denke, das das nicht so ist. Wenn du Daten in die Subitems-Property eines Listitems schreibst, schreibst du ja nur in eine Stringlist. Das erfolgt sofort wenn der Code ausgeführt wird und nicht irgendwann später. "Irgendwann später" erfolgt zwar das Zeichnen des Listviews (weil das ja nur passiert wenn die Paint-Message kommt). Das hat aber nichts mit dem Inhalt selbst zu tun.

Ich glaube, das ein Rechenfehler eurerseits Schuld ist.
Zitat von stephan007:
Insgesamt haben wir 15 Spalten, die erste ist die Caption und dann (über die Subitems) von 0 bis 14.
0 bis 14 ergibt bereits 15 und + Caption wären es 16 Spalten.
Vielleicht ist es aber auch ein Schreibfehler im Post.
Benjamin Schwarze
If I have seen further it is by standing on the shoulders of Giants. (Isaac Newton)
  Mit Zitat antworten Zitat
stephan007

Registriert seit: 2. Mär 2007
48 Beiträge
 
#3

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 3. Mai 2007, 13:52
ups ja stimmt, das mit 0-14 war ein typo. die indizes sind korrekt. allerdings dürfte der draw event noch nicht fertig sein.
wie kann ich feststellen, dass das passiert ist und ich nicht auf eine "unfertige" listview zugreife. das dürfte bei uns nämlich der fall sein, denn bei listview.columns.count wissen wir ja, wieviel spalten wir haben. und wenn ich auf das subitem[i-1] zugreife, dann passt das ja so. nur dürften einige der subitems durch den drawevent noch nicht fertig sein.

denn wie gesagt: ich will die spalten sizen (optimale grösse bzw. zuschieben auf 0 wenn leer).
und das darf ich klarerweise erst dann, bis sich die listview nicht ändert, weil sich sonst die indizes ändern und ich eine indexüberschreitung bekomme (passiert jedesmal beim subitem).
da der index aber vom column.count abhängt (mit -1 klarerweise) sollte der index auch passen.
also muss ich den drawevent abwarten.
wie stelle ich das aber fest. signalisiert mir delphi das irgendwie? wenn ich z.b. einen timeout seit dem letzten elementeintrag von 750 ms mache, dann gehts, nur ist der erste listeneintrag grauslich, weil es eine dreiviertel sekunde dauert, bis das sizen anfängt.

lg,
stephan.
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#4

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 3. Mai 2007, 14:14
hallo, macht ihr das threaded? dann wäre die verwendung von critical sections empfehlenswert.
Lukas Erlacher
Suche Grafiktablett. Spenden/Gebrauchtangebote willkommen.
Gotteskrieger gesucht!
For it is the chief characteristic of the religion of science that it works. - Isaac Asimov, Foundation I, Buch 1
  Mit Zitat antworten Zitat
stephan007

Registriert seit: 2. Mär 2007
48 Beiträge
 
#5

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 3. Mai 2007, 14:34
das ist es ja, wir haben um den listaufbau (nennen wir display) die critical section gelegt. darin bleiben wir aber hängen (deadlock) wenn es beim resizen kracht.
oder meinst du das sizen in eine eigene critical section?
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#6

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 3. Mai 2007, 17:17
Hallo, ihr habt diesen Ablauf:

- multithreaded einfügen
- sobald das einfügen beendet ist, resizen

right?

wenn ihr eine codestelle habt, an der ihr definitiv sagen könnt, das einfügen ist abgeschlossen, dann legt eine Criticalsection an, die am anfang des einfügens angefordert und am ende releast wird.
Ein Thread wartet dann nur auf diese CriticalSection (indem er sie anfordert). Sobald er sie bekommt sendet er eine Windows-Message an den Hauptthread, indem als Reaktion auf diese Message das Sizing vorgenommen wird.

Kleine Zwischenfrage: Benutzt ihr bereits BeginUpdate und EndUpdate für die Listview/die subitems?

wenn ihr keine solche codestelle habt, dann braucht ihr eine generelle "listview-access" critical section. Immer, wenn irgendjemand (sprich, irgendein thread) an die listview ranwill, muss er die critical section betreten. damit kann es eigentlich niemals zu zugriffsfehlern kommen.

Wenn ihr vor Beginn des Scans abschätzen könnt, wie viele Antworten ihr bekommt (bei entsprechender designmöglichkeit auch fehlschläge mit einberechenn und rückmelden!), kannst du da ja noch eine hürde einbauen, die erst nach entsprechender anzahl eingegangener ergebnisse (oder einem master timeout) mit dem sizing anfängt.

BTW:

Zitat:
(sowas wie ein Event "Drawfinished" - in die ListView schreiben ist ja eigentlich auch nichts anderes als ein Draw Event (wird einem erst beim Umfärben einzelner Einträge bewußt)
...eigentlich nur wenn die listview virtuell ist. oder wie genau meinst du das? das hinzufügen/verändern von listitems führt nur dann zum sofortigen redraw, wenn du dich nicht(!) in innerhalb eines Beginupdate/endupdate bereichs befindest, wie ich oben bereits angedeutet habe.
Lukas Erlacher
Suche Grafiktablett. Spenden/Gebrauchtangebote willkommen.
Gotteskrieger gesucht!
For it is the chief characteristic of the religion of science that it works. - Isaac Asimov, Foundation I, Buch 1
  Mit Zitat antworten Zitat
stephan007

Registriert seit: 2. Mär 2007
48 Beiträge
 
#7

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 3. Mai 2007, 23:38
hm und wie mach ich das dann sinnvoll, wenn die einträge zu unterschiedlichen zeiten daherkommen, also je nachdem wann die antwort über tcp retour kommt?

wenn ich einen zeitraum habe, in der ich alle antworten aufsammle, sollte das kein problem sein. aber wenn z.b. eine antwort 5 sec nach der vorherigen kommt, dann nutzt mir das begin und endupdate auch nur bedingt etwas, ganz abgesehen davon dass wirs auch drinnen haben.

das sonderbare dabei (unserem problem) ist aber, dass der crash immer bei unterschiedlichen indexwerten passiert, also mal gleich beim ersten element, mal beim letzten, mal gleich beim ersten subitem, mal beim 10. und dann auch wieder mal garnicht. schaut daher stark nach "netten" racingconditions aus.

deshalb war auch meine überlegung, dass das sizen erst dann beginnen darf, wenn die listview sich nicht mehr ändert, also alle einträge drinnen sind und das draw event fertig ist. dann kann mit dem index nichts mehr passieren.

aber scheinbar wird unser sizer schon aktiv, bevor der draw event fertig ist. stellt sich also (wie schon zu beginn) die frage: wie kann ich feststellen, dass die element fertig eingetragen sind und der draw event abgeschlossen ist und ich keine indexverletzung mehr riskiere.

critical section und begin sowie endupdat haben dabei leider auch nur "bedingt" geholfen.
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#8

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 4. Mai 2007, 07:08
Guten Morgen Stephan,

ich bin sicher, dass die geschilderten Probleme durch einen Implementierungsfehler in "deinem" Programm entstehen. Eine racing condition mit dem internen Zeichenvorgang kann eigentlich nicht vorliegen. Du solltest es mit einer Detailanalyse versuchen. Trenne das Multithreading vom Listview-Handling und untersuche die Problemfelder getrennt voneinander. Die ListView exportiert die Ereignisse OnDeletion() und OnInsert(), die dir die Möglichkeit zu Berechnungen geben. Ein wiederholtes Resizing der Spalten halte ich aber für sehr unangenehm. Üblich ist eine statische Dimensionierung oder - bei häufigen Änderungen am Inhalt - ein Resizing durch den Benutzer über die vorgesehenen Shortcuts (CTRL +).

Grüße vom marabu
  Mit Zitat antworten Zitat
stephan007

Registriert seit: 2. Mär 2007
48 Beiträge
 
#9

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 4. Mai 2007, 09:02
was ich bis jetzt noch vergessen habe ist, dass wir im resizer auch einen "canvas invalid handle" bekommen.

wenn ich das resizen nach jedem einzelnen eintrag aufrufe (also n mal bei n einträgen - was allerdings sehr rechenaufwändig und nicht schön ist) dann funktioniert es problemlos.

hab das jetzt mit 750 ms timeout seit dem letzten ankommenden element gelöst und das funktioniert stabil.
würde mich aber trotzdem interessieren, ob es einen event gibt, der seitens delphi signalisiert, dass das zeichnen (draw event) fertig ist.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#10

Re: ListView: Wie erkennt man, dass Elemente fertig eingetra

  Alt 4. Mai 2007, 09:59
greifst du vom Thread aus auf die Listview eventuell ohne Syncronize zu? anders kann ich mir "canvas invalid handle" nicht erklären.

Zitat:
das ist es ja, wir haben um den listaufbau (nennen wir display) die critical section gelegt. darin bleiben wir aber hängen (deadlock) wenn es beim resizen kracht.
dann fang den Fehler doch mit Try-... ab
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:45 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz