AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units
Thema durchsuchen
Ansicht
Themen-Optionen

Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

Ein Thema von fisipjm · begonnen am 2. Nov 2023 · letzter Beitrag vom 9. Nov 2023
Antwort Antwort
Seite 1 von 2  1 2      
fisipjm

Registriert seit: 28. Okt 2013
298 Beiträge
 
#1

Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 2. Nov 2023, 16:49
Hallo,

ich arbeite gerade an meiner ersten visuellen Komponente in Delphi und habe einige Fragen dazu. Ursprünglich dachte ich, es wäre sinnvoll, zuerst die gesamte Funktionalität zu entwickeln und sie dann in eine visuelle Komponente umzuwandeln. Im Nachhinein scheint das jedoch keine gute Idee gewesen zu sein.

Ich habe eine Klasse erstellt, die von TLayout abgeleitet ist. Dies dient als Grundlage für meine visuelle Komponente, da TLayout bereits viele Grundfunktionen bietet, die ich benötige. Auf diesem Layout habe ich auch eine eigene Button-Komponente erstellt, die von TRectangle abgeleitet ist. Nennen wir diese Klasse einfach TMyButton . Ich habe TMyButton in einer eigenen Unit abgelegt und sie in den Uses-Teil meiner visuellen Komponente aufgenommen. Auf diese Weise kann ich die Komponente im Code erstellen, und sie funktioniert zur Laufzeit einwandfrei.

Das Problem tritt auf, wenn ich versuche, die Komponente zur Entwurfszeit auf die Form zu ziehen. Das funktioniert noch, aber ab diesem Zeitpunkt lässt sich die Form nicht mehr speichern und ein neu laden der Form ist auch nicht mehr möglich. Delphi meldet dann, dass es die Klasse TMyButton nicht finden kann. Ich habe gesehen, dass einige Beispiele alle Klassen in einer Unit zusammenfassen, was jedoch dazu führt, dass die Unit sehr groß wird. Ist dies die einzige Möglichkeit, oder wie sollte das Deployment einer visuellen Komponente in diesem Kontext richtig durchgeführt werden?

Hat jemand bereits Erfahrungen mit visuellen Komponenten und kann mir weiterhelfen?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.993 Beiträge
 
Delphi 12 Athens
 
#2

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 2. Nov 2023, 19:07
Wo und in welchen Units/Packages was drin ist, ist eigentlich vollkommen egal.


Wie kommt TMyButton auf dein LayoutDingens?

Im FormDesigner (DesignTimePackage) müssen alle Komnponenten registriert sein (RegisterComponents/RegisterNoIcon/RegisterClasses ... jenachdem wie die "Sichtbarkeit" ist, bzw. ob in KomponentenPalette drin)

Zur Laufzeit müssen die Klassen auch registriert sein, damit der DFM-Loader sie auch finden/laden kann.

Gibt es für eine Komponente mindestens eine Published-Variable in der Klasse, dann registriert der DFM-Loader diese Klasse (RegisterClass anschließend wieder UnRegisterClass).
z.B. für SubComponenten (die z.B. nicht Owner=Form haben), welche dennoch vom DFM-Loader geladen/erstellt werden, aber die keine Variable besitzen, muß man vorher selber mit RegisterClass ran.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
298 Beiträge
 
#3

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 5. Nov 2023, 13:16
Hi Himitsu,

danke für deine Antwort, ich glaub ich bin noch nicht tief genug in der Materie drin um deine Rückmeldung richtig einzuordnen. Ich versuche dir mal die Fragen zu beantworten:

Wie kommt TMyButton auf dein LayoutDingens?
Meine TMyButtons werden im Create des abgeleiteten Layouts erzeugt, nennen wir das Layout mal TMyLayout. Das ist auch die Klasse, die in der register Procedure registriert wird. Die TMyButtons bekommen TMyLayout als Parent + unterschiedliche OnClickHandler.

Im FormDesigner (DesignTimePackage) müssen alle Komnponenten registriert sein (RegisterComponents/RegisterNoIcon/RegisterClasses ... jenachdem wie die "Sichtbarkeit" ist, bzw. ob in KomponentenPalette drin)
Zur Laufzeit müssen die Klassen auch registriert sein, damit der DFM-Loader sie auch finden/laden kann.
Bedeutet das, dass ich für jede Klasse ein Register mit in die Register Procedure stecken muss? Ich möchte aber nicht, dass TMyButton als Element in der Komponentenpalette zur Verfügung steht, es sollte am Schluss nur TMyLaout zur Auswahl stehen.

Gibt es für eine Komponente mindestens eine Published-Variable in der Klasse, dann registriert der DFM-Loader diese Klasse (RegisterClass anschließend wieder UnRegisterClass).
z.B. für SubComponenten (die z.B. nicht Owner=Form haben), welche dennoch vom DFM-Loader geladen/erstellt werden, aber die keine Variable besitzen, muß man vorher selber mit RegisterClass ran.
Da komm ich nicht ganz mit, hängt vielleicht auch mit der vorhergehenden Frage zusammen.

Grüße
PJM
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.993 Beiträge
 
Delphi 12 Athens
 
#4

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 5. Nov 2023, 14:52
Alle Klassen/Komponenten, welche der FormDesigner, bzw. der DFM-Loader erstellt, die müssen "bekannt" sein, damit er diese Klasse über ihren Namen finden kann.

Wenn ein TMyLayout diese Komponente erstellt, dann wird auch deine Komponete als Owner übergeben?
Steht der erstellte Button anschließend in der DFM drin? (wurde also beim Speichern "gefunden" und vom DFM-Streaming gespeichert, um wieder geladen zu werden)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
298 Beiträge
 
#5

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 6. Nov 2023, 08:36
Moin Himitsu,

Also, ich entwickle in der FMX Ecke, deshalb ich meine .dfm eine .fmx, aber das sollte ja erst mal egal ein.
In der fmx steht nach dem reinladen erst mal alles drin. Ich sehe tatsächlich auch die Komponente wenn ich sie das erste mal auf meine Maske ziehe.
Erst wenn ich das erste mal versuche zu speichern, bzw. in die Codeansicht wechsle und dann wieder in die Designeransicht gehe (Tabs am unteren Rand der IDE), dann bekomme ich den Fehler das er die darunterliegenden Klassen nicht finden kann.

Als Owner übergebe ich immer die jeweils darüberliegende Klasse, also:
Owner von TMyLayout: Maske auf die ich die Komponente gelegt hab
Wowner von TMyButton: TMyLayout
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
298 Beiträge
 
#6

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 6. Nov 2023, 10:18
Alle Klassen/Komponenten, welche der FormDesigner, bzw. der DFM-Loader erstellt, die müssen "bekannt" sein, damit er diese Klasse über ihren Namen finden kann.

Wenn ein TMyLayout diese Komponente erstellt, dann wird auch deine Komponete als Owner übergeben?
Steht der erstellte Button anschließend in der DFM drin? (wurde also beim Speichern "gefunden" und vom DFM-Streaming gespeichert, um wieder geladen zu werden)
Hi,

damit wir nicht die ganze Zeit über hypothetisches reden, hab ich das Verhalten mal nachgestellt. Das ist der Quellcode für die Unit. Einfach in ein Package werfen und als Komponente installieren. Beim versuch das ganze mit x64 laufen zu lassen, erhalte ich die Info, dass TMySpeedButton nicht gefunden werden kann. Das rein ziehen der Komponente funktioniert aber problemlos.

Delphi-Quellcode:
unit uMyVisualLayout;

interface

uses
  System.SysUtils, System.Classes, FMX.Types, FMX.Controls, FMX.Layouts, FMX.StdCtrls, FMX.Objects,
  FMX.Graphics;

Type
  TMyImage = class(TImage)

  private
    FBackupImage: TBitmap;

  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

Type
  TMySpeedbutton = class(TSpeedButton)

  private
    FLabelText: TLabel;
    function GetNewText: String;
    procedure SetNewText(const Value: String);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property NewText: String read GetNewText write SetNewText;
  end;

Type
  TMyLayout = class(TLayout)

  private
    { Private-Deklarationen }
    Speedbutton1, Speedbutton2, Speedbutton3: TMySpeedbutton;
    TopFlowLayout: TFlowLayout;
    procedure ButtonClick(Sender: Tobject);
  protected
    { Protected-Deklarationen }
  public
    constructor Create(AOwner: TComponent); override;
    { Public-Deklarationen }
  published
    { Published-Deklarationen }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('TestVisualComponent', [TMyLayout]);
end;

{ TMyLayout }

procedure TMyLayout.ButtonClick(Sender: Tobject);
begin
  log.d(TSpeedButton(Sender).Name + ' Clicked!');
end;

constructor TMyLayout.Create(AOwner: TComponent);
begin
  inherited;
  TopFlowLayout := TFlowLayout.Create(self);
  TopFlowLayout.Parent := self;
  TopFlowLayout.Align := TAlignLayout.MostTop;

  Speedbutton1 := TMySpeedbutton.Create(self);
  Speedbutton1.Parent := TopFlowLayout;
  Speedbutton1.Align := TAlignLayout.Client;
  Speedbutton1.NewText := 'Speedbutton1';
  Speedbutton1.OnClick := ButtonClick;

  Speedbutton2 := TMySpeedbutton.Create(self);
  Speedbutton2.Parent := TopFlowLayout;
  Speedbutton2.Align := TAlignLayout.Client;
  Speedbutton2.NewText := 'Speedbutton2';
  Speedbutton2.OnClick := ButtonClick;

  Speedbutton3 := TMySpeedbutton.Create(self);
  Speedbutton3.Parent := TopFlowLayout;
  Speedbutton3.Align := TAlignLayout.Client;
  Speedbutton3.NewText := 'Speedbutton3';
  Speedbutton3.OnClick := ButtonClick;

end;

{ TMyImage }

constructor TMyImage.Create(AOwner: TComponent);
begin
  inherited;
  FBackupImage := TBitmap.Create;
end;

destructor TMyImage.Destroy;
begin
  FBackupImage.Free;
  inherited;
end;

{ TMySpeedbutton }

constructor TMySpeedbutton.Create(AOwner: TComponent);
begin
  inherited;
  FLabelText := TLabel.Create(self);
  FLabelText.Parent := self;
  FLabelText.Align := TAlignLayout.Client;
end;

destructor TMySpeedbutton.Destroy;
begin
  FLabelText.Free;
  inherited;
end;

function TMySpeedbutton.GetNewText: String;
begin
  Result := FLabelText.Text;
end;

procedure TMySpeedbutton.SetNewText(const Value: String);
begin
  FLabelText.Text := Value;
end;

end.
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
732 Beiträge
 
#7

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 6. Nov 2023, 10:29
Also mir fehlt da schonmal ein SetSubComponent(True) .
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
298 Beiträge
 
#8

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 6. Nov 2023, 11:33
Also mir fehlt da schonmal ein SetSubComponent(True) .
Hi Oli,

https://docwiki.embarcadero.com/Libr...etSubComponent
Emba meint ich brauch es nur wenn ich was im Published hab, das ich gerne gespeichert hätte. Kannst du bissel näher ausführen für was das gebraucht wird?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.993 Beiträge
 
Delphi 12 Athens
 
#9

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 6. Nov 2023, 22:13
Das SetSubKomponent braucht man nur, wenn man Objekte als Published veröffentlicht.

Normal werden hier nur Zeiger/Verlinkungen gespeichert, aber dadurch weiß der DFM-Writer/Reader dann, dass stattdessen die Eigenschaften der Subkomponente gespeichert werden sollen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 7. Nov 2023 um 08:12 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.993 Beiträge
 
Delphi 12 Athens
 
#10

AW: Visuelle Komponente mit mehreren Klassen in unterschiedlichen Units

  Alt 7. Nov 2023, 02:13
FLabelText.Free; bzw. ist unnötig TMySpeedbutton.Destroy, da es durch den Owner freigegeben wird. Aber Falsch ist es auch nicht.

Ansonsten seh ich eigentlich nichts Schlimmes.
Nach außen sind diese Subkomponenten ja nicht sichtbar, für den DFM-Reader/Writer.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:13 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