Come è possibile creare un componente in fase di esecuzione e quindi utilizzarlo (modifica delle proprietà, ecc.)?Creazione di componenti in fase di esecuzione - Delphi
risposta
Dipende se si tratta di un componente visivo o non visivo. Il principio è lo stesso, ma ci sono alcune considerazioni aggiuntive per ogni tipo di componente.
Per i componenti non visivi
var
C: TMyComponent;
begin
C := TMyComponent.Create(nil);
try
C.MyProperty := MyValue;
//...
finally
C.Free;
end;
end;
Per componenti visivi:
In sostanza componenti visivi vengono creati nello stesso modo come componenti non visivi. Ma devi impostare alcune proprietà aggiuntive per renderle visibili.
var
C: TMyVisualComponent;
begin
C := TMyVisualComponent.Create(Self);
C.Left := 100;
C.Top := 100;
C.Width := 400;
C.Height := 300;
C.Visible := True;
C.Parent := Self; //Any container: form, panel, ...
C.MyProperty := MyValue,
//...
end;
Alcuni spiegazioni al codice di cui sopra:
- Impostando il proprietario del componente (il parametro del costruttore) la componente viene distrutta quando il modulo possessore viene distrutta.
- L'impostazione della proprietà
Parent
rende visibile il componente. Se lo dimentichi, il tuo componente non verrà visualizzato. (E 'facile perdere che uno :))
Se volete molti componenti si può fare lo stesso come sopra, ma in un ciclo:
var
B: TButton;
i: Integer;
begin
for i := 0 to 9 do
begin
B := TButton.Create(Self);
B.Caption := Format('Button %d', [i]);
B.Parent := Self;
B.Height := 23;
B.Width := 100;
B.Left := 10;
B.Top := 10 + i * 25;
end;
end;
Questo aggiungerà 10 pulsanti a sinistra confine della forma. Se si desidera modificare i pulsanti in un secondo momento, è possibile memorizzarli in un elenco. (TComponentList ist più adatto, ma anche dare un'occhiata alle proposte dei commenti a questa risposta)
Come assegnare i gestori di eventi:
È necessario creare un metodo del gestore di eventi e assegnarlo al proprietà dell'evento.
procedure TForm1.MyButtonClick(Sender: TObject);
var
Button: TButton;
begin
Button := Sender as TButton;
ShowMessage(Button.Caption + ' clicked');
end;
B := TButton.Create;
//...
B.OnClick := MyButtonClick;
Molto facile. Chiama Crea. Esempio:
procedure test
var
b : TButton;
begin
b:=TButton.Create(nil);
b.visible:=false;
end;
Questo crea un componente (TButton è un componente) in fase di esecuzione e imposta la proprietà visibile.
Per il costruttore: passare nil se si desidera gestire la memoria da soli. Passa a un puntatore un altro componente se desideri che venga distrutto quando l'altro componente viene distrutto.
È necessario passare il puntatore al proprietario dell'elemento. TButton.Create (proprietario); –
Questo codice non viene compilato –
> necessario per il proprietario Non necessariamente. TButton.Create (zero); è un codice valido ma ora devi distruggerlo esplicitamente. È utile creare componenti visivi con un proprietario nullo. – Despatcher
per semplificare il processo di creazione componente runtime, è possibile utilizzare GExperts.
- Creare un componente (o più componenti) visivamente e impostarne le proprietà.
- Selezionare uno o più componenti ed eseguire GExperts, Componenti su codice.
- Incolla il codice generato nella tua applicazione.
- Rimuovi componente/i dal designer del modulo visivo.
Esempio:
var
btnTest: TButton;
btnTest := TButton.Create(Self);
with btnTest do
begin
Name := 'btnTest';
Parent := Self;
Left := 272;
Top := 120;
Width := 161;
Height := 41;
Caption := 'Component creation test';
Default := True;
ParentFont := False;
TabOrder := 0;
end;
Ottimo consiglio! È esattamente quello che avrei suggerito. GExperts è un ottimo strumento da usare con Delphi. –
... oppure è possibile progettarlo nell'editor visivo e quindi inserire un picco nel file .dfm. Fondamentalmente la stessa identica cosa c'è nel testo – Earlz
Gracias. Preferisco scrivere da solo tutte le cose (so che è forse reinventare la ruota ma ho più controllo su di essa) comunque sembra che lo strumento GExpert non cambi in puro codice e che suoni sia buono. Grazie ancora per un consiglio. – QMaster
Ma se io non di certo so quanti componenti voglio creare, ad esempio, se dipende dalla decisione dell'utente. Quindi, come posso dichiarare i componenti dinamicamente?
La risposta è stata suggerita - il modo più semplice è un elenco di oggetti (componenti). TObjectList è il più semplice da usare (in unità contnrs). Le liste sono fantastiche!
In Form1 Public
MyList: TObjectList;
procedure AnyButtonClick(Sender: TObject);
// è possibile ottenere più sofisticati e dichiarare // TNotifyevents e assegnarli ma lascia mantenerlo semplice :) . . .
procedure Tform1.AnyButtonClick(Sender: TObject);
begin
If Sender is TButton then
begin
Case Tbutton(Sender).Tag of
.
.
.
// Or You can use the index in the list or some other property
// you have to decide what to do
// Or similar :)
end;
end;
procedure TForm1.BtnAddComponent(Sender: TObJect)
var
AButton: TButton;
begin
AButton := TButton.Create(self);
Abutton. Parent := [Self], [Panel1] [AnOther Visual Control];
AButton.OnClick := AnyButtonClick;
// Set Height and width and caption ect.
.
.
.
AButton.Tag := MyList.Add(AButton);
end;
un elenco di oggetti può contenere qualsiasi oggetto visivo o no, ma che ti dà un overhead aggiunto di smistamento quali elementi sono che - meglio avere elenchi correlati se si vuole più controlli dinamici su pannelli simili, per esempio.
Nota: come altri commentatori, potrei aver semplificato per brevità ma spero che l'idea. Hai bisogno di un meccanismo per gestire gli oggetti una volta creati e gli elenchi sono eccellenti per questa roba.
Alcuni componenti sovrascrivono il metodo "Caricato". Questo metodo non verrà chiamato automaticamente se si crea un'istanza in fase di runtime. Verrà chiamato da Delphi quando il caricamento dal file di modulo (DFM) è completo.
Se il metodo contiene codice di inizializzazione, l'applicazione potrebbe mostrare un comportamento imprevisto quando viene creata in fase di esecuzione. In questo caso, controlla se il writer del componente ha utilizzato questo metodo.
Se si annidano i controlli di vittoria in Caselle di gruppo/Controlli di pagina/Ecc ..., penso che sia utile avere anche la casella del gruppo principale. Ho notato una forte diminuzione dei tempi di chiusura delle finestre quando si fa questo, invece di avere il proprietario sempre il modulo principale.
Durante una ricerca su "creazione di un modulo delphi utilizzando un modello basato su xml", trovo qualcosa di utile che indica RTTI e utilizza open tools api (ToolsApi.pas penso). Dai un'occhiata alle interfacce nell'unità.
Vorrei aggiungere che quando si aggiungono dinamicamente i controlli ... è consigliabile aggiungerli a un elenco di oggetti (TObjectList) come suggerito in < 1> da @Despatcher.
procedure Tform1.AnyButtonClick(Sender: TObject);
begin
If Sender is TButton then
begin
Case Tbutton(Sender).Tag of
.
.
.
// Or You can use the index in the list or some other property
// you have to decide what to do
// Or similar :)
end;
end;
procedure TForm1.BtnAddComponent(Sender: TObJect)
var
AButton: TButton;
begin
AButton := TButton.Create(self);
Abutton. Parent := [Self], [Panel1] [AnOther Visual Control];
AButton.OnClick := AnyButtonClick;
// Set Height and width and caption ect.
.
.
.
AButton.Tag := MyList.Add(AButton);
end;
è necessario aggiungere l'Unità 'Contnrs' alla tua lista Usi. I.e System.Contnrs.pas alla base Unità contenitori E si possono avere molti elenchi di oggetti. Suggerisco di utilizzare una TObjectList per ogni tipo di controllo che si utilizza ad es.
Interface
Uses Contnrs;
Type
TMyForm = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
Var
MyForm: TMyForm;
checkBoxCntrlsList: TObjectList; //a list for the checkBoxes I will createin a TPanel
comboboxCntrlsList: TObjectList; //a list of comboBoxes that I will create in some Form Container
questo consente di manipolare/gestire facilmente ciascun controllo poiché saprete quale tipo di controllo è, ad es.
Var comboBox: TComboBox;
I: Integer;
begin
For I = 0 to comboboxCntrlsList.Count -1 do // or however you like to identify the control you are accessing such as using the tag property as @Despatcher said
Begin
comboBox := comboboxCntrlsList.Items[I] as TComboBox;
...... your code here
End;
end;
Ciò consente di utilizzare per i metodi e le proprietà di tale controllo Non dimenticare di creare le TObjectLists, magari sotto forma di creare eventi ...
checkBoxCntrlsList := TObjectList.Create;
comboboxCntrlsList := TObjectList.Create;
Questo è esempio come emulare il tag button su Evernote
unit Unit7;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, CHButton, Vcl.ExtCtrls, RzPanel, CHPanel, RzCommon,RzBmpBtn, Vcl.StdCtrls;
type
// This is panel Button
TButtonClose = class (TRzPanel)
CloseButton : TRzBmpButton;
procedure CloseButtonClick(Sender: TObject);
procedure CloseButtonMouseEnter(Sender: TObject);
procedure MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TForm7 = class(TForm)
CHButton1: TCHButton;
RzPanel1: TRzPanel;
RzBmpButton1: TRzBmpButton;
procedure CHButton1Click(Sender: TObject);
procedure RzBmpButton1Click(Sender: TObject);
procedure RzPanel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure RzPanel1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure RzPanel1MouseEnter(Sender: TObject);
procedure RzBmpButton1MouseEnter(Sender: TObject);
procedure FormMouseEnter(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form7: TForm7;
MyCloseButton : TButtonClose;
implementation
{$R *.dfm}
// constructor for on the fly component created
constructor TButtonClose.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// Set Events for the component
Self.OnMouseEnter := Self.CloseButtonMouseEnter;
Self.OnMouseDown := Self.MouseDown;
Self.OnMouseUp := Self.MouseUp;
Self.Height := 25;
// Close button on top panel Button
// Inherited from Raize Bitmap Button
CloseButton := TRzBmpButton.Create(self);
// Set On Click Event for Close Button
CloseButton.OnClick := Self.CloseButtonClick;
// Place Close Button on Panel Button
CloseButton.Parent := self;
CloseButton.Left := 10;
CloseButton.Top := 5;
CloseButton.Visible := False;
// Setting the image for the button
CloseButton.Bitmaps.Up.LoadFromFile(ExtractFilePath(Application.ExeName)+'\close.bmp');
end;
procedure TButtonClose.CloseButtonClick(Sender: TObject);
begin
// Free the parent (Panel Button)
TControl(Sender).Parent.Free;
end;
procedure TButtonClose.CloseButtonMouseEnter(Sender: TObject);
begin
// Show the Close button
CloseButton.Visible := True;
end;
procedure TButtonClose.MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
// Emulate Button down state, since it is panel
TRzPanel(Sender).BorderOuter := fsLowered;
end;
procedure TButtonClose.MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
// Emulate Button up state, since it is panel
TRzPanel(Sender).BorderOuter := fsRaised;
end;
destructor TButtonClose.Destroy;
begin
inherited Destroy;
end;
procedure TForm7.FormCreate(Sender: TObject);
begin
// Create Panel Button on the fly
MyCloseButton := TButtonClose.Create(self);
MyCloseButton.Caption := 'My Button';
MyCloseButton.Left := 10;
MyCloseButton.Top := 10;
// Don't forget to place component on the form
MyCloseButton.Parent := self;
end;
procedure TForm7.FormMouseEnter(Sender: TObject);
begin
if Assigned(RzBmpButton1) then
RzBmpButton1.Visible := False;
// Hide when mouse leave the button
// Check first if myCloseButton Assigned or not before set visible property
if Assigned(MyCloseButton.CloseButton) then
MyCloseButton.CloseButton.Visible := False;
end;
procedure TForm7.RzBmpButton1Click(Sender: TObject);
begin
TControl(Sender).Parent.Free;
end;
procedure TForm7.RzBmpButton1MouseEnter(Sender: TObject);
begin
RzBmpButton1.Visible := True;
end;
procedure TForm7.RzPanel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
TRzPanel(Sender).BorderOuter := fsLowered;
end;
procedure TForm7.RzPanel1MouseEnter(Sender: TObject);
begin
RzBmpButton1.Visible := True;
end;
procedure TForm7.RzPanel1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
TRzPanel(Sender).BorderOuter := fsRaised;
end;
procedure TForm7.CHButton1Click(Sender: TObject);
begin
FreeAndNil(Sender);
end;
end.
- 1. Creazione di componenti UI accessibili in Delphi
- 2. Come aggiungere componenti a un JPanel in fase di esecuzione
- 3. Creazione di oggetti in fase di esecuzione in Ruby
- 4. Impedisce a Delphi IDE di creare le icone dei componenti in fase di progettazione
- 5. Componenti da evitare in Delphi
- 6. Creazione di componenti MXML personalizzati
- 7. Componenti di scansione TWAIN per Delphi
- 8. Come creare e collegare attributo personalizzato al campo in fase di esecuzione in Delphi
- 9. Creazione di una classe per un'interfaccia in fase di esecuzione, in C#
- 10. Creazione dinamica di un elenco di argomenti della funzione C++ in fase di esecuzione
- 11. Impostazione tipo generico in fase di esecuzione
- 12. Modifica proprietà log4j in fase di esecuzione
- 13. Modifiche al vtable in fase di esecuzione
- 14. scegliere una monade in fase di esecuzione
- 15. Sostituisci bean in fase di esecuzione
- 16. Castle Windsor Resolve in fase di esecuzione
- 17. javafx cambia css in fase di esecuzione
- 18. Ottieni binding IIS in fase di esecuzione
- 19. metodo call in fase di esecuzione
- 20. Rileva versione Python in fase di esecuzione
- 21. Modifica implementazione/classe in fase di esecuzione
- 22. Cambiare l'orientamento in fase di esecuzione
- 23. FederatedAuthentication.WSFederationAuthenticationModule è nullo in fase di esecuzione
- 24. Caricamento giare in fase di esecuzione
- 25. esclusione in fase di esecuzione __setattr__
- 26. Aumenta disposizione PySpark in fase di esecuzione
- 27. Aggiungere animazione in fase di esecuzione
- 28. Estendere classe in fase di esecuzione
- 29. Ridimensionamento dei controlli in fase di esecuzione
- 30. Cambia carattere in fase di esecuzione
Ma se non so sicuramente quanti componenti voglio creare, ad es. se dipende dalla decisione dell'utente. Quindi, come posso dichiarare i componenti dinamicamente? –
La distinzione se passare nil o un altro componente come proprietario non ha nulla a che fare con il componente che è visibile o meno, solo con la durata dell'oggetto. Un componente invisibile che non è stato liberato nello stesso metodo potrebbe essere creato proprio come nel secondo frammento e essere liberato automaticamente dal proprietario. – mghie
s/visible/visual/g – mghie