AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

String in Listview Data ?

Ein Thema von Blamaster · begonnen am 30. Mär 2010 · letzter Beitrag vom 31. Mär 2010
Antwort Antwort
Seite 1 von 3  1 23      
Blamaster

Registriert seit: 20. Jul 2007
230 Beiträge
 
#1

String in Listview Data ?

  Alt 30. Mär 2010, 11:07
Hi,

ich möchte einen String im .Data eines Listviewitems hinterlegen.

Wie genau macht man das ?

Ich habe es gerade mal so versucht:

Delphi-Quellcode:
var
 test: string;
 item: TListItem;
begin
 test := 'Ich liege in der Listview.Items.Item.data'
 
 item := Listview.Items.Add;
 item.Caption := 'Irgendwas';
 item.Data := Pointer(test);
end;
Und dann zum auslesen:

ShowMessage(String(ListView.Items.Item[x].Data)); Dabei entstehen aber große Unregelmäßigkeiten. Mal steht der string im Data so wie er soll, mal nur merkwürdige Zeichen, mal garnichts, mal gibt es eine exception. Wo liegt mein Fehler ?

Mfg Yannic
  Mit Zitat antworten Zitat
IceBube

Registriert seit: 9. Jul 2008
178 Beiträge
 
#2

Re: String in Listview Data ?

  Alt 30. Mär 2010, 11:15
Hallo!

Also bei mir funktioniert das einwandfrei. Fehler sind bei mir nicht aufgetreten, auch wenn man nichts in die Data schreibt..kommt keine Exception...

lg
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

Re: String in Listview Data ?

  Alt 30. Mär 2010, 11:17
Der String darf nicht in einer lokalen Variable gespeichert sein. Dann sollte es gehen.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

Re: String in Listview Data ?

  Alt 30. Mär 2010, 11:18
Eventuell schlägt hier die Referenzzählung des Strings zu, wenn du den String über Pointer(...) zuweißt, wird da die Referenzzählung nicht behandelt.
Wird dann der übergebene String mal freigegeben, dann ist er weg und in .Data steht nur ein Zeiger zu einem nicht mehr existierendem String.

versuch es mal so:
Delphi-Quellcode:
//zuweisen
String(item.Data) := test;

// auslesen
test := String(item.Data);
$2B or not $2B
  Mit Zitat antworten Zitat
Blamaster

Registriert seit: 20. Jul 2007
230 Beiträge
 
#5

Re: String in Listview Data ?

  Alt 30. Mär 2010, 11:30
@ himitsu

String(item.Data) := test; Dabei bekomme ich einen Error "Left side cannot be assigned to"

Kann evtl. meine for schleife das Problem sein ?

Delphi-Quellcode:
for i := 0 to x do
begin
test := 'Ich liege in der Listview.Items.Item.data an der Stelle + ' ' + IntToStr(i);

item := Listview.Items.Add;
item.Caption :=
'Irgendwas';
item.Data := Pointer(test);
end;
Ein Pointer ist ja ein Zeiger zeigt dieser nur zum zuweisen auf test, so dass der String danach fest im item.Data liegt ?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

Re: String in Listview Data ?

  Alt 30. Mär 2010, 11:40
tja, entweder zu sorgst dafür, daß "test" nie freigegeben/verändert wird, solange die Referenz in item.Data liegt,

oder du mußt eben doch die Referenzzählung beachten

Delphi-Quellcode:
var P: Pointer;

// zuweisen
String(P) := test;
item.Data := P;

// auslesen
test := String(item.Data);

// freigeben
P := item.Data;
String(P) := '';

oder du legst doch einen Record, mit deinem String, in item.Data ab


oder du gehst über einen PChar (natürlich mußt du dafür selber den Speicher reservieren und den Stringinhalt dareinkopieren), welchen du dann an item.Data übergibst.
(und freigeben nicht vergessen)
$2B or not $2B
  Mit Zitat antworten Zitat
Blamaster

Registriert seit: 20. Jul 2007
230 Beiträge
 
#7

Re: String in Listview Data ?

  Alt 30. Mär 2010, 12:40
Hi,

sprich dein Beispielcode müsste in meinem Fall so aussehen ?

Delphi-Quellcode:
var
  P: Pointer;
  test: string;
  i: integer;
  item: TListItem;
begin
 for i := 0 to 10 do
 begin
  item := TListItem.Items.Add;
  item.caption := 'Test ' + IntToStr(i);
  test := 'Ich liege in der Listview.Items.Item.data an der Stelle ' + IntToStr(i);
  String(P) := test;
  item.Data := P;
 end;
end;
Wenn ja, dann geht es so auch nicht selbe Probleme wie in Post 1.

Mfg Yannic
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#8

Re: String in Listview Data ?

  Alt 30. Mär 2010, 12:58
Hallo,

ich nehme für meine TListItem.Data immer eine Klasse
die in einer Liste steckt.
Nat. darf die Liste nicht lokal sen, sondern gehört ins Form.

In deinem Fall würde auch eine TStringList reichen.

Wie schon weiter vorn gesagt, darf die String-Variable
nicht lokal sein.

Data ist ja nur ein Zeiger auf das Original.
wenn das Original weg ist, zeigt Data irgendwohin.


Heiko
Heiko
  Mit Zitat antworten Zitat
Blamaster

Registriert seit: 20. Jul 2007
230 Beiträge
 
#9

Re: String in Listview Data ?

  Alt 30. Mär 2010, 14:03
Hi,

schade das Data so umständlich zu verwenden ist.

also nochmal zum verständnis. Data enthält einen pointer der auf die richtigen Daten zeigt. Wenn die Variable auf die Pointer zeigt nun so nicht mehr existiert gibt es Probleme logisch.

Was ändert sich dann aber durch eine globale Variable ? Diese existiert dann zwar immernoch nur wenn ich eine einfache Stringvariable habe und sich alle Datafelder auf diese beziehen, dann müssten doch alle den aktuellen Wert der Stringvariableenthalten oder nicht ?

So wie ich es verstehe:

- Data -> Enthält pointer auf Objekt -> Pointer verweist auf globale Variable test

Jetzt lese ich Data aus:

- Data liest seinen Pointer der ihm sagt wo er nachsehen muss sucht dann nach der variable test und liest sie aus.

Sprich wenn am Schluss wo es um die Ausgabe geht in der globalen Variable 'blub' steht, dann würde jedes durch die for schleife definierte Datafeld nun auf 'blub' zeigen oder nicht ?

Mit einer Progressbar geht das ganze recht einfach ind verständlich:

Delphi-Quellcode:
var
 pb: TProgessBar
 item: TListItem;
 i: integer;
begin
 for i := 0 to 10 do
 begin
  item := Listview.Items.Add
  item.Caption := 'Progressbar ' + IntToStr(i);
  pb := TProgressbat.Create(nil);
  item.Data := pb;
 end;
end;
Wieso lässt sich das mit einem string nicht auch so einfach erledigen ?

Wie genau war das mit mir würde auch eine Strnglist reichen gemeint ?

Mfg Yannic
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

Re: String in Listview Data ?

  Alt 30. Mär 2010, 14:24
.Data ist nicht wirklich umständlich nutzbar ... es ist wie mit jedem anderen Zeiger/Pointer auch.
Und hier war nunmal die eigentlich gute Referenzzählung schuld, welche man durch solch einen Cast absichtlich umgeht.

Einziges Problem bei Properties ist, daß sie keinen gleichzeitigen Schreib- und Lesezugriff erlauben, weswegen String(item.Data):=irgendwas; nicht ging.



Die hoika schon sagte, wenn man auf was zeigen will, dann muß man dafür sorgen, daß dieses nicht in der Zwischenzeit freigegeben wird.
Wobei Objekte keine referenzzählung haben und man sie daher auch direkt, in einen Pointer gekastet, in Data eintragen könnte.

Delphi-Quellcode:
item.Data := Pointer(Test);
//auslesen
Test := PChar(item.Data);
//oder
Test := String(item.Data); // wenn Test ein String ist
ist praktisch das Selbe wie
Delphi-Quellcode:
item.Data := PChar(Test);
//auslesen
Test := PChar(item.Data);
außer daß bei PChar für einen Leerstring (nil) nicht nil, sondern ein Zeiger auf einen mit #0 gefüllten Speicherplatz übergeben wird.

Wird jetzt Test verändert, freigegeben oder verschoben, dann zeigt .Data natürlich immernoch auf die Stelle des "alten" Strings und somit teigt String(item.Data) nicht mehr auf einen String und es knallt oder es kommt im günstigsten Falle nur Schrott raus.

Delphi-Quellcode:
var
  P: Pointer;
  i: integer;
  item: TListItem;
begin
  for i := 0 to 10 do
  begin
    item := TListItem.Items.Add;
    item.caption := 'Test ' + IntToStr(i);
    String(P) := 'Ich liege in der Listview.Items.Item.data an der Stelle ' + IntToStr(i);
    item.Data := P;
  end;
end;
Delphi-Quellcode:
test := 'Ich liege in der Listview.Items.Item.data an der Stelle ' + IntToStr(i);
String(P) := test;
item.Data := P;
test := '';
Hier wird P wie eine Stringvariable behandelt, es wird also bei Zuweisung auch der Referenzzähler des String erhöht.
Gibt man nun test wieder frei, dann wird der Referenzzähler erniedrigt, aber da ja noch die Referenz für String(P) existiert, wird der String nicht freigegeben, sondern existiert weiterhin in P.
Die Folge ist nun, daß man beim löschen des Items auch den String in item.Data mit freigeben muß, da ja sonst ein Speicherleck entsteht.


Fazit:
Wird etwas direkt in .Data abgelegt, dann muß man es dort auch wieder freigeben,
auch wenn man ein Objekt nur da reinlegt.

Wärend bei hoikas Vorschlag das Objekt in einer externen Liste liegt und in P nur eine Kopie des Instanzzeigers.
Bei ihm muß/darf man das Objekt in .Data also nicht freigeben, da hierfür die Liste verantwortlich ist, welche ja quasi das Original besitzt.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 22:56 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