Delphi-PRAXiS

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 Problem mit selbst erstellter Komponente (https://www.delphipraxis.net/67962-problem-mit-selbst-erstellter-komponente.html)

windi 22. Apr 2006 14:24


Problem mit selbst erstellter Komponente
 
Hi Leute,

ich habe ein kleines Problem mit einer selbst geschriebenen Komponente. Sie basiert auf einem Frame in dem dynamisch Shapes geladen werden. Durch die Eigenschaft "BufferSize" kann die Anzahl der Shapes verändert werden. Alle Shapes speichere ich mir in eine TList. Das ganze funktioniert auch soweit ganz gut, wenn ich die BufferSize-Eigenschaft zur Laufzeit ändere. Sobald ich diese aber im Objektinspektor editiere, erhalte ich ne Zugriffsverletzung im Modul 'rtl70.bpl'. Danach lässt sich Delphi nur noch im Task-Manager abschießen.

Beim ändern der BufferSize zerstöre ich als erstes alle Shape-Objekte in der Liste und erzeuge diese danach von neuem. Soweit ich herausgefunden habe, liegt das Problem im zerstören der Shapes. Ich habe schon ein wenig mit der Notification-Prozedur herumexperimentiert, aber noch keine richtige Lösung gefunden. Ich bin für jede Hilfe echt dankbar!!

Hier ein Auszug aus dem Quellcode:

Delphi-Quellcode:
TBuffer = class(TFrame)
  private
    FPlaces: TList;
    function GetBufferSize: Byte;
    procedure SetBufferSize(Size: Byte);
    procedure DeleteShapes;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  published
    property BufferSize: Byte read GetBufferSize write SetBufferSize;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

implementation

{$R *.dfm}

procedure TBuffer.DeleteShapes;
 begin
  while (FPlaces.Count > 0) do
   begin
    TShape(FPlaces.Items[0]).Destroy;
    FPlaces.Delete(0);
   end;
 end;

function TBuffer.GetBufferSize: Byte;
 begin
  Result := FPlaces.Count;
 end;

procedure TBuffer.SetBufferSize(Size: Byte);
var i: Byte;
    PlaceShape: TShape;
 begin
  DeleteShapes;
  for i := 0 to Size-1 do
   begin
    PlaceShape := TShape.Create(Self);
    PlaceShape.Parent := Self;
    PlaceShape.Name := 'Place' + IntToStr(i));
    FPlaces.Add(PlaceShape);
   end;
 end;

procedure TBuffer.Notification(AComponent: TComponent; Operation: TOperation);
var i: Integer;
 begin
  inherited Notification(AComponent, Operation);
   if (FPlaces <> NIL) then
    for i := FPlaces.Count-1 downto 0 do
     if ((Operation = opRemove) and (FPlaces.Items[i] <> NIL) and (AComponent = FPlaces.Items[i])) then
      begin
       FPlaces.Items[i] := NIL;
       Break;
      end;
 end;

constructor TBuffer.Create(AOwner: TComponent);
 begin
  inherited Create(AOwner);
  FPlaces := TList.Create;
  SetBufferSize(4);
 end;

destructor TBuffer.Destroy;
 begin
  DeleteShapes;
  FPlaces.Destroy;
  inherited Destroy;
 end;

end.

Hawkeye219 22. Apr 2006 14:31

Re: Problem mit selbst erstellter Komponente
 
Hallo,

warum verwendest du keine Delphi-Referenz durchsuchenTObjectList? Die kümmert sich selbst um die Freigabe der enthaltenen Objekte. Zudem könntest du beim Erzeugen der Shapes NIL als Owner übergeben, da du die Freigabe ja selbst übernimmst.

Gruß Hawkeye

SirThornberry 22. Apr 2006 14:31

Re: Problem mit selbst erstellter Komponente
 
ich denke dein Problem ist das du im Notification Event einfach
Delphi-Quellcode:
FPlaces.Items[i]
auf nil setzt. Letztendlich behältst du dabei aber trotzdem noch einen Pointer in deiner Liste auf den du dann später wohl noch zugreifst.

So rufst du zum Beispiel im DeleteShapes folgendes auf:
Delphi-Quellcode:
TShape(FPlaces.Items[0]).Destroy;
Zu dem Zeitpunkt kann aber "fPlaces.Items[0]" = nil sein weil du es ja im Notification auf nil gesetzt hast. Anstelle des Setzens auf Nil wäre es also sinnvoller einfach "FPlaces.Delete" aufzurufen.

windi 22. Apr 2006 15:09

Re: Problem mit selbst erstellter Komponente
 
Vielen Dank für Eure Hilfe! Der Tipp mit der TObjectList und dem Setzen der TShape.Create(NIL) hat geholfen. :-D


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