Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Komponente mit TStrings Property erstellen (https://www.delphipraxis.net/76758-komponente-mit-tstrings-property-erstellen.html)

GuenterS 9. Sep 2006 09:59


Komponente mit TStrings Property erstellen
 
Hallo,

wie der Titel schon aussagt, habe ich ein kleines Problem beim Erstellen einer Komponente, welche ein TStrings Objekt als Property im OI anbieten soll.

Ich habe mich beim Erstellen, an diverse Tutorials gehalten (zumindest versucht) aber jedesmal, wenn ich die Komponente dann auf ein Formular ziehe, der Property SQL (das ist die TStrings Property) einen String zuweise und das ganze dann noch ein zweites mal versuche, bekomme ich Zugriffsverletzungen, so, dass nur noch das Beenden von Delphi hilft.

Ich verwende Delphi 7 Professional.

Delphi-Quellcode:
unit GSQuery;

interface

uses
  SysUtils, Classes;

type
  TGSQuery = class(TComponent)
  private
    FSQL: TStringList;
    procedure setSQL(const Value: TStringList);
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    constructor Create(aOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published-Deklarationen }
    property SQL: TStringList read FSQL write setSQL;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('GS', [TGSQuery]);
end;

{ TGSQuery }

constructor TGSQuery.Create(aOwner: TComponent);
begin
  inherited;
  FSQL := TStringList.Create;
end;

destructor TGSQuery.Destroy;
begin
  FSQL.Free;
  inherited;
end;

procedure TGSQuery.setSQL(const Value: TStringList);
begin
  FSQL := Value;
end;

end.
Was mache ich da nur falsch?

Hawkeye219 9. Sep 2006 10:35

Re: Komponente mit TStrings Property erstellen
 
Hallo Günter,

der Fehler steckt in der Setter-Methode. Durch die direkte Zuweisung überschreibst du die im Constructor initialisierte Referenz auf das TStringList-Objekt mit einem neuen Zeiger, was zunächst nur zu einem Speicherleck führt. Gleichzeitig übernimmt aber nun das Query-Objekt die Verantwortung für die übergebene Liste, die du vermutlich nach der Zuweisung zur SQL-Eigenschaft freigibst. Damit ist dann der Zeiger innerhalb des Query-Objekts ungültig!

Besser ist es, im Setter den Inhalt der Liste zu kopieren:

Delphi-Quellcode:
FSQL.Assign(Value);
Noch ein Vorschlag: ändere den Datentyp von FSQL ab in TStrings. Dadurch kannst du später beliebige TStrings-Nachfolger (z.B. TMemo.Lines) zuweisen. Im Constructor von TGSQuery muß natürlich weiterhin ein TStringList-Objekt instanziiert werden, da TStrings abstrakte Methoden enthält.

Gruß Hawkeye

GuenterS 9. Sep 2006 10:54

Re: Komponente mit TStrings Property erstellen
 
Danke :)

Wenn ich Assign verwende klappt es, ein Query Objekt kommt aber nicht wirklich vor, das ist wirklich der komplette Quelltext der Komponente ... die Query kommt erst später dazu :)


Das mit TStrings habe ich aber nicht hinbekommen, da meckert der Compiler immer über inkompatible Typen.

Delphi-Quellcode:
unit GSQuery;

interface

uses
  SysUtils, Classes;

type
  TGSQuery = class(TComponent)
  private
    FSQL: TStringList;
    procedure setSQL(const Value: TStrings);
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    constructor Create(aOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published-Deklarationen }
    property SQL: TStrings read FSQL write setSQL;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('GS', [TGSQuery]);
end;

{ TGSQuery }

constructor TGSQuery.Create(aOwner: TComponent);
begin
  inherited;
  FSQL := TStringList.Create;
end;

destructor TGSQuery.Destroy;
begin
  FSQL.Free;
  inherited;
end;

procedure TGSQuery.setSQL(const Value: TStrings);
begin
  FSQL.Assign(Value);
end;

end.

Hawkeye219 9. Sep 2006 11:04

Re: Komponente mit TStrings Property erstellen
 
Du mußt die Deklaration im private-Abschnitt ebenfalls ändern:

Delphi-Quellcode:
private
  FSQL: TStrings;
Falls du innerhalb der Komponente einmal auf die TStringList-Eigenschaften zugreifen mußt, benötigst du einen TypeCast:

Delphi-Quellcode:
TStringList(FSQL).Sorted := True;
Bei der SQL-Eigenschaft sehe ich diese Notwendigkeit aber nicht.

PS: mit "Query-Objekt" meinte ich eine Instanz deiner TGSQuery-Klasse.

Gruß Hawkeye

GuenterS 9. Sep 2006 11:23

Re: Komponente mit TStrings Property erstellen
 
Dankeschön, jetzt funktioniert das mal soweit wie ich es wollte.

Poolspieler 18. Mär 2013 21:29

AW: Komponente mit TStrings Property erstellen
 
Hallo zusammen,
das Thema ist zwar schon älter - ich habe aber bei gleichem Source-Code folgendes Problem:

Im OI kann ich schön Strings in die Stringliste eintragen (mit dem automatisch öffnenden String-Listen-Editor).
Soweit so gut.

Wenn ich das Programm aber starte, dann sind die eingetragenen Werte nicht mehr vorhanden --> gibt es da einen Trick?
Wo sollen die auch her kommen?:shock:

Code:
constructor TGSQuery.Create(aOwner: TComponent);
begin
   inherited;
   FSQL := TStringList.Create;
end;
Im Konstruktor wird FSQL erzeugt --> ist also LEER.:?
WIE komme ich nun an die zur Designzeit eingetragenen Werte?:cyclops:

Wäre schön, wenn jemand eine Antwort für mich hätte.

Viele Grüße,

Poolspieler

Poolspieler 18. Mär 2013 22:15

AW: Komponente mit TStrings Property erstellen
 
Hallo,
ich bin ein bisschen weiter:

In FSQL sind die Werte schon vorhanden. Allerdings erst nach einem noch unbekannten Zeitpunkt.

Problem ist, dass ich versuche, diese Werte im CONSTRUCTOR einer Combobox zuzuweisen.
Und zum Zeitpunkt des Konstruktors ist FSQL tatsächlich noch LEER!

Code:
constructor TGSQuery.Create(aOwner: TComponent);
 begin
    inherited;
    FSQL := TStringList.Create;
 end;
combobox.Items.Assign(FSQL);
Frage:
WANN werden die Werte nach FSQL geladen?
Ich habe schon das Ereignis AfterConstruction probiert --> da ist FSQL noch LEER!
Mit dem Debugger konnte ich den Zeitpunkt auch noch nicht finden. :(

Hat jemand eine Idee?

Viele Grüße,

Poolspieler

Volker Z. 18. Mär 2013 22:33

AW: Komponente mit TStrings Property erstellen
 
Hallo,

hast Du denn einen Setter für FSQL in Deiner Klasse TGSQuery? Schau Dir mal den Quellcode in Post #3 an; da sollte die Lösung stehen.

Gruß

Poolspieler 18. Mär 2013 22:49

AW: Komponente mit TStrings Property erstellen
 
Hallo Volker,
danke für Deine Antwort!

Ja, habe ich schon.

Allerdings stand ich auch gerade ganz schön auf der Leitung:

Im Konstruktor muss es natürlich heißen:
Code:
constructor TGSQuery.Create(aOwner: TComponent);
  begin
     inherited;
     ...
     combobox := TComboBox.Create(Self);
     ...
     FSQL := combobox.Items;
     // und NICHT:
     //FSQL := TStringList.Create;
  end;
Was will ich denn mit ZWEI Listen???????? :stupid:
Es ist halt doch schon spät...

Viele Grüße,

Poolspieler

Gutelo 19. Jan 2014 08:37

AW: Komponente mit TStrings Property erstellen
 
Noch eine weiterfuehrende Frage,

ich habe auch eine TStrings Liste in den Properties einer eigenen Komponente. Zur Designzeit werden die eingetragenen Werte in der Liste durch eine Setter procedure uebernommen. Nun werden die eigentragenen Werte in der Stringliste dazu verwendet ein Array zu fuellen (wird ebenfalls in der Setter procedure erledigt). Das funktioniert waehrend des Designs prima, allerdings ist das Array zur Laufzeit wieder leer.

Die Komponente ist von TPaintBox abegeleitet. Da das Array vom Typ record ist und einige werte zur Laufzeit geaendert werden kann ich das Erstellen des Arrays nicht einfach in die paint procedure packen, da sonst jedesmal standardwerte im Array stehen.

Gibt es eine procedure die nur einmal nach dem constructor ausgefuehrt wird?

Gutelo


Edit: Habs jetzt so geloest in der paint procedure auch wenns nich ganz optimal ist:

if Length(Arr) = 0 then FillArr(SList, Arr);

Arr ist das Array, SList ist TStrings mit Werten und FillArr eine Prozedur die die Werte aus SList in Arr eintraegt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:17 Uhr.
Seite 1 von 2  1 2   

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