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/)
-   -   Klasse mit Properties als Property (https://www.delphipraxis.net/159389-klasse-mit-properties-als-property.html)

Ninow 25. Mär 2011 19:20

Klasse mit Properties als Property
 
Hallo DP'ler,

ich hänge jetzt schon seit ca. 3 Tagen an einem Problem, hab auch schon die Suche angestrengt und nix brauchbares gefunden.

Also ich habe mir eine PropertyKlasse erstellt:

Delphi-Quellcode:
{...}
type
  TBackGround = class(TPersistent)
    private
      FBackgroundAlignment: TBackgroundAlignment;
      FBeginColor: TColor;
      FEndColor: TColor;
      procedure SetBackgroundAlignment(Value: TBackgroundAlignment);
      procedure SetBeginColor(Value: TColor);
      procedure SetEndColor(Value: TColor);
    published
      property BackgroundAlignment: TBackgroundAlignment read FBackgroundAlignment
        write SetBackgroundAlignment default baStandard;
      property BeginColor: TColor read FBeginColor write SetBeginColor default clBtnFace;
      property EndColor: TColor read FEndColor write SetEndColor default clBtnFace;
  end;
{...}
und habe eine Komponente von der Klasse TPanel abgeleitet:

Delphi-Quellcode:
unit MyPanel;

interface
uses
  ExtCtrls, Controls, Graphics, Windows, Classes;

type
  TMyPanel = class(TPanel)
    private
      FBackGround: TBackGround;
      procedure SetBackGround(NewBackGround: TBackGround);
    published
      property Background: TBackGround read FBackGround write SetBackGround;
  end;

procedure Register;


implementation

procedure Register;
begin
  RegisterComponents('Meine Komponenten', [TMyPanel]);
end;

{ TMyPanel }

procedure TMyPanel.SetBackGround(NewBackGround: TBackGround);
begin
  FBackGround.Assign(NewBackGround);

  Invalidate;
end;
...so.

Und jetzt meine Frage, wie bekomme ich es hin, dass der Objectinspector mir meine PropertyKlasse als kleines DropDown Menü anzeigt? (Wie Font oder Margins)

Er zeigt mir nur meine Property "Background" mit "(TBackGround)" und ein [+] an, aber wenn ich auf das [+] klicke, wird es zu [-] aber er klappt es nicht auf.

Danke schonmal!

Beste Grüße
Ninow

mkinzler 25. Mär 2011 19:23

AW: Klasse mit Properties als Property
 
Du musst einen entsprechenden PropertyEditor implementieren und registrieren

Ninow 25. Mär 2011 20:21

AW: Klasse mit Properties als Property
 
Kurze Zwischenfrage TPropertyEditor befindet sich ja in DesignEditors.

Der Compiler meldet aber das er DesignEditors.dcu nicht finden kann warum?

Ninow 25. Mär 2011 20:50

AW: Klasse mit Properties als Property
 
Okay Zwischenfrage erledigt...

Aphton 25. Mär 2011 21:07

AW: Klasse mit Properties als Property
 
Definiere die einzelnen Properties als published

Delphi-Quellcode:
{..}
published
  property BeginColor;
  property EndColor;
{..}
Weiters musst du für die Instanzierung in TMyPanel selbst sorgen. Dh. im Konstruktor & Destruktor die Instanz per TKlassenname.Create erstellen und anschließend im Destruktor per Free zerstören!

Edit: Sorry, hab mich verguggt. Du müsstest die Propertys normalerweise als Public definieren und anschließend in Kurzform auch als published, soweit ich mich nicht irre... Hatte aber nicht viel am Hut mit Komponentenentwicklung & IDE

Ninow 25. Mär 2011 21:24

AW: Klasse mit Properties als Property
 
@Aphton: Die Properties müssen unter published stehen, da sie ja zur Entwicklungszeit verändert werden sollen.

WM_CLOSE 25. Mär 2011 21:38

AW: Klasse mit Properties als Property
 
guggt doch mal, wie es bei datasources gemacht wird. Ich glaube nicht, dass die einen Property-Editor benutzen.

himitsu 25. Mär 2011 21:40

AW: Klasse mit Properties als Property
 
Zitat:

Zitat von Ninow (Beitrag 1091072)
@Aphton: Die Properties müssen unter published stehen, da sie ja zur Entwicklungszeit verändert werden sollen.

TPersistent und Nachkommen > Standardsichtbarkeit = Published
TObjekt und Nachkommen (außer TPersistent) > Standardsichtbarkeit = Public

durch das
Delphi-Quellcode:
{$M+}

sx2008 25. Mär 2011 22:32

AW: Klasse mit Properties als Property
 
Ausserdem muss auch die Methode TBackGround.Assign implementiert werden.
Der Objektinspektor muss unter Umständen eine Kopie des TBackGround Objekts erzeugen und benötigt daher die Assign-Methode.
Bei älteren Delphiversionen kam dann bei fehlender Implementation die Exception "Klasse Txyz kann Txyz nicht zugewiesen werden".
Möglich, dass die Exception in neueren IDEs abgefangen wird.
Delphi-Quellcode:
procedure TBackGround.Assign(Source:TPersistent); {override}
begin
  if Source is TBackGround then
  begin
    FBackgroundAlignment := TBackGround(Source).FBackgroundAlignment;
    ...
  end
  else
    inherited; // wichtig! darf nicht fehlen
end;

Uwe Raabe 26. Mär 2011 00:08

AW: Klasse mit Properties als Property
 
Es könnte auch helfen, den Background von TComponent abzuleiten und als Subkomponente des Panels anzulegen (
Delphi-Quellcode:
FBackground.SetSubComponent(true);
). Dann werden die Einstellungen nämlich automatisch auch in der DFM gespeichert. Der Objektinspektor wird dann den Background mit einem "+" darstellen, womit man an dessen Properties kommt. Da du die Deklaration von TBackgroundAlignment nicht mitlieferst, kann man dazu noch nichts sagen. Wenn es ein Aufzählungstyp ist, musst du den lediglich registrieren damit der ObjektInspektor damit klar kommt. Der Property-Editor für TBackground erübrigt sich damit.

Ninow 26. Mär 2011 11:12

AW: Klasse mit Properties als Property
 
In der TBackgroundAlignment befindet sich nur:

Delphi-Quellcode:
type
  TBackgroundAlignment = (baStandard, baLeftToRight, baTopToBottom);
Das kann er mir ja auch anzeigen.

Also ich habe jetzt verschiedene Sachen probiert:

Das mit dem PropertyEditor bekomme ich irgendwie nicht hin, ausser das halt

Delphi-Quellcode:
  TBackGroundProperty = class(TPropertyEditor)
    //Was soll ich hier machen
  end;
@sx2008: TBackGround.Assign hab ich eingebaut, keine Veränderung.

@Uwe: Hab ich auch ausprobiert, hab

Delphi-Quellcode:
{...}
type
  TBackGround = class(TComponent)
    {...}
  end;
 
type
  TMyPanel = class(TPanel)
    private
      FBackGround: TBackGround;
      procedure SetBackGround(Value: TBackGround);
    published
      property BackGround: TBackGround read FBackGround write SetBackGround;
    public
      constructor Create(AOwner: TComponent); override;
  end;

{...}

constructor Create(AOwner: TComponent);
begin
  FBackGround.SetSubComponent(true);
  inherited;
end;
erstellt und auch installiert. Dann habe ich mein anderes Projekt aufgemacht wo ich mir das anschaue und da kommt jetzt Adressfehler. Also mach ich was falsch, aber was!?

Gruß Ninow

Aphton 26. Mär 2011 14:31

AW: Klasse mit Properties als Property
 
Zitat:

Zitat von Ninow (Beitrag 1091133)
In der TBackgroundAlignment befindet sich nur:

Delphi-Quellcode:
type
  TBackgroundAlignment = (baStandard, baLeftToRight, baTopToBottom);
Das kann er mir ja auch anzeigen.

Also ich habe jetzt verschiedene Sachen probiert:

Das mit dem PropertyEditor bekomme ich irgendwie nicht hin, ausser das halt

Delphi-Quellcode:
  TBackGroundProperty = class(TPropertyEditor)
    //Was soll ich hier machen
  end;
@sx2008: TBackGround.Assign hab ich eingebaut, keine Veränderung.

@Uwe: Hab ich auch ausprobiert, hab

Delphi-Quellcode:
{...}
type
  TBackGround = class(TComponent)
    {...}
  end;
 
type
  TMyPanel = class(TPanel)
    private
      FBackGround: TBackGround;
      procedure SetBackGround(Value: TBackGround);
    published
      property BackGround: TBackGround read FBackGround write SetBackGround;
    public
      constructor Create(AOwner: TComponent); override;
  end;

{...}

constructor Create(AOwner: TComponent);
begin
  FBackGround.SetSubComponent(true);
  inherited;
end;
erstellt und auch installiert. Dann habe ich mein anderes Projekt aufgemacht wo ich mir das anschaue und da kommt jetzt Adressfehler. Also mach ich was falsch, aber was!?

Gruß Ninow

Bei Create steht der Klassenname nicht! Es müsste heißen
constructor TMyPanel.Create(..)
Eigne dir die Grundlagen an, falls du das nicht wusstest!
Weiters müsstet du im Konstruktor Speicher für das Feld FBackground allozieren...

Ninow 26. Mär 2011 14:51

AW: Klasse mit Properties als Property
 
Ah,
wär ein Fehler den der Compiler melden würd ;) sry habs vercheckt hinzuschreiben.
Natürlich muss die Klasse da stehen. Trotz alldem funktioniert es nicht.

Ach ja, >.< hab ich mal wieder im Eifer des Gefechts vergessen...

Uwe Raabe 26. Mär 2011 15:31

AW: Klasse mit Properties als Property
 
Zitat:

Zitat von Ninow (Beitrag 1091133)
@Uwe: Hab ich auch ausprobiert, hab
...
Delphi-Quellcode:
constructor Create(AOwner: TComponent);
begin
  FBackGround.SetSubComponent(true);
  inherited;
end;
erstellt und auch installiert. Dann habe ich mein anderes Projekt aufgemacht wo ich mir das anschaue und da kommt jetzt Adressfehler. Also mach ich was falsch, aber was!?

So geht's:

Delphi-Quellcode:
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FBackGround := TBackGround.Create(Self);
  FBackGround.Name := 'Background';
  FBackGround.SetSubComponent(true);
end;

sx2008 28. Mär 2011 03:28

AW: Klasse mit Properties als Property
 
Die Klasse TBackGround muss ausserdem noch registriert werden:
Delphi-Quellcode:
initialization
  RegisterClass(TBackGround);
end;
Ich glaube jetzt ham wir alle Vorrausetzungen:
* vom TPersistent ableiten
* Properties published deklarieren
* Assign-Methode überschreiben
* Klasse registrieren
Von TCompoent abzuleiten ist nicht norwendig.
Wie man sieht ist z.B. die Klasse TFont nicht von TComponent abgeleitet und man kann die Eigenschaften trotzdem im Objektinspektor editieren.

Ninow 28. Mär 2011 17:51

AW: Klasse mit Properties als Property
 
Ah, dass hab ich garnicht gewusst, nja mein Projekt "eigene Komponenten" steckt noch in den Kinderschuhen. So einiges weiß ich auch noch nicht, muss ich noch ranglotzen! Danke euch!

mjustin 29. Mär 2011 19:14

AW: Klasse mit Properties als Property
 
Zitat:

Zitat von himitsu (Beitrag 1091080)
TPersistent und Nachkommen > Standardsichtbarkeit = Published
TObjekt und Nachkommen (außer TPersistent) > Standardsichtbarkeit = Public
[/DELPHI]

Das kannte ich noch nicht, oder ist es ein Missverständnis? Macht der Compiler einen klassenabhängigen Unterschied bei der Sichtbarkeit?

Bisher war ich immer davon ausgegangen dass bei

Delphi-Quellcode:
TMeineKlasse = class(TIrgendwas)
  Geheim: string;
end;
die Sichtbarkeit von "Geheim" immer published ist, unabhängig von der Vorfahrklasse.

Der Unterschied zeigt sich wenn man $M+ hinzufügt. Wenn TObject -> public gälte, würde $M+ der Klasse keine RTTI Informationen hinzufügen, bei TEgal -> published gälte, dann doch.

Mike


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