![]() |
Allgemeine Frage zu Zuweisungen von Instanzen
Hallo, ich habe zwar grad ein Tutorial durchgelesen, aber es werfen sich doch noch Fragen auf.
Ich habe zwei Instanzen z.B.
Delphi-Quellcode:
Durch diese Zuweisungen wird jetzt der notwendige Speicher für die Listen reserviert und der Zeiger darauf in "Liste1" und "Liste2" gespeichert, oder?
var Liste1, Liste2: TStringlist;
Liste1:=TStringlist.Create; Liste2:=TStringlist.Create;
Delphi-Quellcode:
Dies bewirkt nun das der Zeiger auf den Speicher von Liste1 auf Liste2 kopiert wird. Damit greifen beide Variablen nun auf den selben Speicherbereich (auf die gleiche Liste) zu. Der vorher zugewiesene Speicherbereich von Liste2 ist damit zwar noch im Speicher vorhanden, aber nicht mehr erreichbar (und damit verwaist), oder?
Liste2:=Liste1;
Delphi-Quellcode:
Das sollte demnach auch funktionieren, da ja durch die Variablendeklaration der Speicher für den Zeiger auf eine Liste erzeugt wurde und nun der Inhalt von Liste1 auch über Liste2 erreichbar ist, oder?
var Liste1, Liste2: TStringlist;
Liste1:=TStringlist.Create; Liste2:=Liste1; Jetzt noch eine etwas spezieller auf mein eigentliches Problem zugeschnittene Frage: Ich möchte eine Klasse von TEdit ableiten und dieser eine Funktion Autocomplete verpassen. Für diese Funktion benötige ich natürlich auch eine Liste, die die Strings enthält, in denen gesucht wird. Also ungefähr so:
Delphi-Quellcode:
Meine Idee ist, irgendwo im aufrufenden Programm zu schreiben:
TXTEdit = class(TEdit)
private FAutocomplete: Boolean; FSearchList: TStringlist; protected procedure DoAutocomplete; procedure CMChanged(var Message: TMessage); message CM_CHANGED; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; property Autocomplete: Boolean read FAutocomplete write FAutocomplete default False; property Searchlist: TStringlist read FSearchlist write FSearchlist; end;
Delphi-Quellcode:
wobei EineStringliste einiges sein kann, z.B. EinStringGrid.Cols[0] oder EineListbox.Items
MyEdit.Searchlist:=EineStringliste;
MyEdit.Autocomplete:=True; Leider funktioniert das nicht so ganz wie ich will, sondern führt noch zu einer Zugriffsverletzung. Eigentlich sollte es doch nicht notwendig sein eine Instanz von FSearchlist im constructor zu erzeugen, mir reicht es ja, den Zeiger auf die zugewiesenen Liste zu haben, oder? Ich habe zwar beide Varianten bereits ohne Erfolg ausprobiert, aber mir gehts darum grundsätzlich zu verstehen, ob das so gehen müsste. Ich hoffe, jemand kann mir auf meine Anfängerfragen eine Antwort geben. Es ist echt tragisch, man glaubt, jetzt kann ich genug, um ohne Hilfe weiter zu kommen und schon stößt man auf das nächste Problem. Guido |
Re: Allgemeine Frage zu Zuweisungen von Instanzen
Delphi-Quellcode:
property Searchlist: TStringlist read FSearchlist write FSearchlist; // Falsch
property Searchlist: TStrings read FSearchlist write FSearchlist; // Besser |
Re: Allgemeine Frage zu Zuweisungen von Instanzen
Also beide Annahmen oben stimmen.
Die 'verwaiste' TStringList aus der ersten Annahme nennt man übrigens ein Speicherleck. -> Speicher der angefordert wird aber nie freigegeben wird.
Delphi-Quellcode:
Pfui. :zwinker:
property Searchlist: TStringlist read FSearchlist write FSearchlist;
Delphi-Quellcode:
Und dann weiter:
[...]
function getSearchList:TStringlist; [...] property Searchlist: TStringlist read getSearchList write FSearchlist;
Delphi-Quellcode:
Somit bekommst Du die Instanz der Searchlist genau dann, wenn Du das erste mal drauf zugreifst und räumst sie wieder auf, wenn Dein Edit zerstört wird.
function TXTEdit.getSearchList: TStringList;
begin if not Assigned(FSearchList) then FSearchList := TStringList.Create(); result := FSearchList; end; destructor TXtEdit.Destory; begin if Assigned(FSearchList) then FreeAndNil(FSearchList); inherited; end; |
Re: Allgemeine Frage zu Zuweisungen von Instanzen
Delphi-Quellcode:
Mit TStringlist und TStrings bin ich mir im Gebrauch nicht immer sicher, aber da TListbox.Items auch vom Typ TStrings ist, wird es wohl so sein.
property Searchlist: TStringlist read FSearchlist write FSearchlist; // Falsch
property Searchlist: TStrings read FSearchlist write FSearchlist; // Besser
Delphi-Quellcode:
Sollte es nicht so herum sein. Ich erzeuge doch die Liste, wenn ich an Searchlist etwas zuweise, oder?
[...]
function getSearchList:TStrings; [...] property Searchlist: TStrings read FSearchList write SetSearchlist; ABER Warum muss ich diese Liste überhaupt erzeugen? Der Speicher für die Liste ist doch bereits durch die Liste vorhanden, die ich an das XTEdit zuweisen möchte. Mir würde ja ein Zeiger darauf ausreichen (Annahme 2) UND erzeuge ich da nicht ein Speicherleck, wenn ich für FSearchlist Speicher reserviere und dieser dann meine "externe" Liste zuweise? Oder bin ich voll daneben? |
Re: Allgemeine Frage zu Zuweisungen von Instanzen
Hallo Guido,
Zitat:
![]() Gruß Hawkeye |
Re: Allgemeine Frage zu Zuweisungen von Instanzen
Zitat:
Sorry, aber als Entwickler erwarte ich von einem Control, das es alles mitbring was es braucht. Wäre ja noch schöner, wenn ich eine ComboBox auf mein Formular ziehe, dass ich dem dann die StringListe in denen die Items stecken auch noch selber ezeugen und zuweisen müsste. Nein, so Dinger hat das Control mitzubringen, und ich muss mich nur noch drum kümmern, dass das richtige da drin steht. |
Re: Allgemeine Frage zu Zuweisungen von Instanzen
Eine Gegenfrage...warum willst du die Liste außerhalb der Componente erzeugen, wenn sie eh nur von der Componente benutzt wird ? :)
Das mit dem direkten Zuweisen der Zeiger funktioniert deshalb nicht, weil es eben Objekt sind und die nicht nur Daten enthalten. Hinzu kommt, das deine Liste in der Komponente eine Property ist, d.h. da spielt dann noch das Streaming-System für VCL-Komponenten mit rein (wichtig um das z.B. in DFM-Dateien zu speichern) sowie die RTTI. Ich gehe mal davon aus das du später diese Liste im Objektinspektor editieren willst, dir aber ggf. mehrfach laden bei mehreren XEdit's sparen möchtest. Dann hier mal ein Beispiel wie es funktioniert: Die Componente (also..der entscheidende Teil davon):
Delphi-Quellcode:
Get und Set-Methoden sind nicht unbedingt notwendig, das die Liste beim erzeugen der Komponente gleich mit erzeugt wird und beim zerstören der Komponente freigegeben wird. Das ist wichtig, damit die Liste später auch in der DFM-Datei landet.
TXEdit = class(TEdit)
PRIVATE fsearchlist:TStrings; PUBLIC Constructor Create(AOwner:TComponent); Destructor Destroy;Override; PUBLISHED property Searchlist : TStrings read fsearchlist write fsearchlist; END; IMPLEMENTATION Constructor TXEdit.Create(AOwner:Tcomponent); begin inherited create(AOwner); fsearchlist := TStringlist.create; end; Destructor TXEdit.Destroy; begin fsearchlist.free; inherited; end; Nun zum Programm, das gerne eine Liste an mehrere XEdits verteilen will:
Delphi-Quellcode:
Feddich..alle 3 Edits enthalten nun ein kopie der daten aus ilist. :)
Procedure TForm1.Button1Click(Sender:TObject);
var iList : TStrings; begin iList := TStringlist.create; iList.loadfromfile('C:\Searchlist.txt'); XEdit1.Searchlist.assign(iList); XEdit2.Searchlist.assign(iList); XEdit3.Searchlist.assign(ilist); ilist.free; end; Hoffe das hilft. |
Re: Allgemeine Frage zu Zuweisungen von Instanzen
Danke für die Infos bisher :-D
@Hawkeye: Nein, da verschwende ich keinen Gedanken daran, weil mir die Combobox nicht gefällt. Die Daten, mit denen mein Autovervollständigen arbeiten soll werden aus einem StringGrid kommen, das aus einer Datenbank gefüllt wird. Ich habe jetzt mal was probiert, was sogar (weitgehend) funktioniert, aber noch Fragen bei mir aufwirft.
Delphi-Quellcode:
Wenn ich die Zeile in FormDestroy nicht einfüge, dann kommt es zu einer ungültigen Zeigeroperation. Warum?
type
TXTEdit = class(TEdit) private FAutocomplete: Boolean; FBAutocomplete: Boolean; FSearchList: TStrings; //FOnAutocomplete: TXTAutocompleteEvent; protected procedure DoAutocomplete; procedure CMChanged(var Message: TMessage); message CM_CHANGED; public constructor Create(AOwner: TComponent);Override; destructor Destroy; override; property Autocomplete: Boolean read FAutocomplete write FAutocomplete default False; //property OnAutocomplete: TXTAutocompleteEvent read FOnAutocomplete write FOnAutocomplete; property Searchlist: TStrings read FSearchlist write FSearchlist; end; TForm3 = class(TForm) ListBox1: TListBox; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private-Deklarationen } Edit: TXTEdit; public { Public-Deklarationen } end; var Form3: TForm3; implementation {$R *.dfm} constructor TXTEdit.Create(AOwner: TComponent); begin inherited Create(AOwner); FSearchlist:=TStrings.Create; end; destructor TXTEdit.Destroy; begin FSearchlist.Free; inherited Destroy; end; procedure TXTEdit.DoAutocomplete; var I, StartPos: Integer; begin if assigned(FSearchlist) then begin for I:=0 to FSearchlist.Count-1 do begin if (Text='') or (LowerCase(FSearchlist.Strings[I])=LowerCase(Text)) then begin // if assigned(FOnAutocomplete) then // OnAutocomplete(I); Exit; end; if StrLComp(PChar(LowerCase(FSearchlist.Strings[I])), PChar(LowerCase(Text)), Length(Text)) = 0 then begin StartPos := Length(Text); Text := Text + Copy(FSearchlist.Strings[I], StartPos + 1, Length(FSearchlist.Strings[I])); SelStart := StartPos; SelLength := Length(Text) - StartPos; // if assigned(FOnAutocomplete) then // OnAutocomplete(I); Exit; end; end; end; end; procedure TXTEdit.CMChanged(var Message: TMessage); begin if FAutocomplete then DoAutocomplete; inherited; end; procedure TForm3.FormCreate(Sender: TObject); begin Edit:=TXTEdit.Create(self); Edit.Parent:=Form3; Edit.Searchlist:=Listbox1.Items; end; procedure TForm3.FormDestroy(Sender: TObject); begin Edit.Searchlist:=nil; //Warum brauche ich das??? end; end. |
Re: Allgemeine Frage zu Zuweisungen von Instanzen
Delphi-Quellcode:
Das Formular will dann die ListBox aufräumen, die Items der Listbox, die die Listbox selber aufräumen will, wurde aber schon vom Edit aufgeräumt (ode rumgekehrt).
procedure TForm3.FormCreate(Sender: TObject);
begin Edit:=TXTEdit.Create(self); Edit.Parent:=Form3; Edit.Searchlist:=Listbox1.Items; // <-- hier überschreibst Du die Instanz end; Bei den Items musst Du die per Assign von der Listbox auf das Edit kopieren. |
DP-Maintenance
Dieses Thema wurde von "Phoenix" von "Object-Pascal / Delphi-Language" nach "VCL / WinForms / Controls" verschoben.
Eigentlich gehts hier ja auch eher um Controls ;-) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:10 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