![]() |
class(TPersistent) - Zugriff auf "höhere" Prozedur
Hi
Ich habe eine eigene Komponente, welche eine Hauptklasse beinhaltet (abgeleitet von TPaintbox) und mehrere Unterklassen (abgeleitet von TPersistent), die zum Teil wiederum einige Unterklassen, abgeleitet von Tpersistent, beinhalten. Dies dient dazu im Objektinspektor eine Art "Treeview" darzustellen. [Vielleicht blöd ausgedrückt ^^], also wie "Font". Jetzt möchte ich bei einer Änderung einer Property bzw. Subproperty eine Procedure / Function der Hauptklasse aufrufen. Das Problem ist nur das die Unterklasse, wo die Änderung geschieht, nichts von der Hauptklasse und deren Procedures weiss. (Es kann sein, dass die Änderung zum Beispiel in der 5. Unterklasse einer Hauptklasse geschieht.) Wie kann ich also von einer Unterklasse die Procedures und Functions der Hauptklasse aufrufen (Beweggrund: die Hauptklasse kennt alle Variablen die in der Komponente/Hauptklasse vorkommen, was zum Zeichnen der Kopmonente wichtig ist) ??? |
Re: class(TPersistent) - Zugriff auf "höhere" Proz
Ich würde in den Unterklassen ein Event auslösen und dieses in der Hauptklasse dann verarbeiten. Das hat den Vorteil, dass die Unterklasse keine Informationen von der übergeordneten Klasse benötigt.
|
Re: class(TPersistent) - Zugriff auf "höhere" Proz
und wie würde das dann aussehen. Quelltext technisch :-D
|
Re: class(TPersistent) - Zugriff auf "höhere" Proz
wenn du beim Create der unterclassen (TComponent) den Owner angegeben hast könntest du dich anhand dessen nach oben durchhangeln.
|
Re: class(TPersistent) - Zugriff auf "höhere" Proz
funktioniert das auch wenn die Unterklassen von TPersistent abgeleitet sind ???
|
Re: class(TPersistent) - Zugriff auf "höhere" Proz
1. Wie würde der Constructor dann aussehen ??
2. Kann ich mich über "Owner" hochangeln ?? |
Re: class(TPersistent) - Zugriff auf "höhere" Proz
Für
![]() Für das OffScreenBitmap und andere untergeordnete Klassen hat die Ereignis-Variante genügt, zur Vereinfachung habe ich noch eine gemeinsame Basisklasse geschrieben:
Delphi-Quellcode:
Die Implementierung in die Basisklasse sah dann so aus:
TNotifyingPersistent = class(TPersistent)
private FOnChange: TNotifyEvent; protected procedure Change; virtual; public property OnChange: TNotifyEvent read FOnChange write FOnChange; end; [...] { TNotifyingPersistent } procedure TNotifyingPersistent.Change; begin if Assigned(FOnChange) then FOnChange(Self); end;
Delphi-Quellcode:
Für die View-Property habe ich aber Zugriff auf das Image gebraucht, deshalb muss hier zusätzlich zum Ereignis der Owner angegeben werden:
TMathImage = class(TCustomControl)
private [...] FBit: TMathBitmap; procedure SomeEventhandler(Sender: TObject); published [...] property MathBitmap: TMathBitmap read FBit write SetBit; end; procedure TMathImage.SomeEventhandler(Sender: TObject); begin Redraw; end; constructor TMathImage.Create; begin inherited; [...] FBit := TMathBitmap.Create; FBit.OnChange := SomeEventhandler; end;
Delphi-Quellcode:
Der Zugriff ist also problemlos über FOwner möglich (wobei hier ein FOwner: TCustomControl ohne Forward-Deklaration gereicht hätte).
TMathImage = class; // Forward-Deklaration
TMathFloatRectClass = class(TNotifyingPersistent) private FOwner: TMathImage; [...] public constructor Create(AOwner: TMathImage); procedure NormalizeRect; end; { TMathFloatRectClass } constructor TMathFloatRectClass.Create; begin inherited Create; FOwner := AOwner; TestRect; end; procedure TMathFloatRectClass.NormalizeRect; var yRel, yCenter: MathFloat; begin // xAbs / yAbs = xRel / yRel // yRel = yAbs / xAbs * xRel if Assigned(FOwner) and (FOwner.Height <> 0) and (FOwner.Width <> 0) then with FRect do begin yRel := FOwner.Height / FOwner.Width * (Right - Left); yCenter := (Top + Bottom) / 2; Top := yCenter + yRel / 2 * (Ord(Top > yCenter) * 2 - 1); Bottom := yCenter + yRel / 2 * (Ord(Bottom > yCenter) * 2 - 1); Change; end; end; Endergebnis: ![]() |
Re: class(TPersistent) - Zugriff auf "höhere" Proz
ich hab das jetzt so versucht zu lösen, indem ich den Owner bei Create übergebe und in einer Variable speichere.
Jetzt weiss ich nur nicht von welchem Typ der Owner sein muss ?? Das Problem ist, wenn der Owner den Typ der Hauptklasse hat, muss diese vorher deklariert sein. Dann kann aber die Hauptklasse keine Variable vom Typ der Unterklasse haben, weil diese noch nicht bekannt ist. |
Re: class(TPersistent) - Zugriff auf "höhere" Proz
Zitat:
Auf die Art kann man die Klassen auch schön entkoppeln, da nicht zwangsläufig eine Dorfstraßen-Kommune entstehen muss, in der jede Klasse jede andere kennt. :) |
Re: class(TPersistent) - Zugriff auf "höhere" Proz
Zitat:
Delphi-Quellcode:
//EDIT: bisschen nachgebessert...
type
TX = class; //<-- das ist die "forward" Deklaration TY = class(...) private FOwner: TX; public constructor Create(AOwner: TX); property Owner: TX read FOwner; end; TX = class(...) private FChild: TY; public property Child: TY read FChild; end; |
Re: class(TPersistent) - Zugriff auf "höhere" Proz
1. DANKE an alle die mir geholfen haben
2. Ich hab es jetzt geschafft.
Delphi-Quellcode:
unit TestOwner;
interface uses Windows, Messages, SysUtils, Classes, Controls, ExtCtrls; type TUnter = class(TPersistent) private FZahl : Integer; FOnChange : TNotifyEvent; procedure SetZahl(const Value: Integer); protected procedure Change; virtual; published property OnChange: TNotifyEvent read FOnChange write FOnChange; property Zahl : Integer read FZahl write SetZahl; end; type TTestOwner = class(TPaintbox) private { Private declarations } FMain : TUnter; protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Upgrade(Sender: TObject); published { Published declarations } property Main : TUnter read FMain write FMain; end; procedure Register; implementation procedure Register; begin RegisterComponents('My Own', [TTestOwner]); end; { TTestOwner } constructor TTestOwner.Create(AOwner: TComponent); begin inherited Create(AOwner); FMain := TUnter.Create; FMain.OnChange := Upgrade; end; destructor TTestOwner.Destroy; begin FMain.Free; inherited Destroy; end; procedure TTestOwner.Upgrade(Sender: TObject); begin Self.Canvas.TextOut(Self.FMain.FZahl,1,'Hallo'); end; { TUnter } procedure TUnter.Change; begin if Assigned(FOnChange) then FOnChange(Self); end; procedure TUnter.SetZahl(const Value: Integer); begin FZahl := Value; Change; end; end. |
Re: class(TPersistent) - Zugriff auf "höhere" Proz
Wieso willst du denn einen "published" Event "OnChange" machen, wenn du ihn direkt wieder belegst. Folgende Zeilen sollten dein Problem auch lösen (nicht getestet). Wie gesagt, wenn du alles unter ein type schreibst, dann kannst du "TTestOwner" forward deklarieren.
Delphi-Quellcode:
unit TestOwner;
interface uses Windows, Messages, SysUtils, Classes, Controls, ExtCtrls; type TTestOwner = class; TUnter = class(TPersistent) private FOwner: TTestOwner; FZahl : Integer; procedure SetZahl(const Value: Integer); protected procedure Change; virtual; public constructor Create(AOwner: TTestOwner); property Owner : TTestOwner read FOwner; published property Zahl : Integer read FZahl write SetZahl; end; TTestOwner = class(TPaintbox) private { Private declarations } FMain : TUnter; protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Upgrade(Sender: TObject); published { Published declarations } property Main : TUnter read FMain write FMain; end; procedure Register; implementation procedure Register; begin RegisterComponents('My Own', [TTestOwner]); end; { TTestOwner } constructor TTestOwner.Create(AOwner: TComponent); begin inherited Create(AOwner); FMain := TUnter.Create(Self); end; destructor TTestOwner.Destroy; begin FMain.Free; inherited Destroy; end; procedure TTestOwner.Upgrade(Sender: TObject); begin Self.Canvas.TextOut(Self.FMain.FZahl,1,'Hallo'); end; { TUnter } constructor TUnter.Create(AOwner: TTestOwner); begin inherited Create; FOwner := AOwner; end; procedure TUnter.Change; begin FOwner.Upgrade; end; procedure TUnter.SetZahl(const Value: Integer); begin if Value <> FZahl then begin FZahl := Value; Change; end; end; end. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:29 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