2011-12-17 4 views
8

ho un piccolo problema. Sto cercando di creare in Delphi7 un elenco di componenti in fase di esecuzione e ridimensionarli con l'evento .OnResize del modulo ma non serve ... non riesco a capire come farlo.Come faccio a fare riferimento a componenti creati in fase di esecuzione piuttosto che nella finestra di progettazione del modulo?

Ecco il mio codice:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    //ExtCtrls 
    panel: TPanel; 
    memo: TMemo; 
    splitter: TSplitter; 
    list: TListBox; 
begin 
    panel := TPanel.Create(Self); 
    list := TListBox.Create(Self); 
    splitter := TSplitter.Create(Self); 
    memo := TMemo.Create(Self); 

    with panel do 
    begin 
    Parent := Form1; 
    BevelOuter := bvNone; 
    Top := 12; 
    Left := 12; 
    Height := Form1.Clientheight - 24; 
    Width := Form1.Clientwidth - 24; 
    end; 

    with list do 
    begin 
    Parent := panel; 
    Align := alClient; 
    Top := 0; 
    Height := panel.Height; 
    end; 

    with splitter do 
    begin 
    Parent := panel; 
    Top := 0; 
    Width := 12; 
    Align := alLeft; 
    end; 

    with memo do 
    begin 
    Parent := panel; 
    Top := 0; 
    Left := 0; 
    Width := round(panel.Width/4) * 3; 
    Height := panel.Height; 
    Align := alLeft; 
    end; 
end; 

devo registrare qualche modo i loro nomi al fine di utilizzarli in caso di modulo? O forse, per creare una classe e includerli?

Qualsiasi tipo di aiuto è molto apprezzato! Grazie in anticipo.

risposta

9

Le variabili sono locali rispetto alla procedura in cui sono state create in modo tale che non è possibile fare riferimento a tali variabili utilizzando tali variabili al di fuori di tale procedura. La soluzione è di renderli campi della classe form.

type 
    TForm1 = class(TForm) 
    procedure FormResize(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    private 
    FPanel: TPanel; 
    FMemo: TMemo; 
    FSplitter: TSplitter; 
    FList: TListBox; 
    end; 

Allora il vostro gestore di eventi FormResize può fare riferimento a loro.

procedure TForm1.FormResize(Sender: TObject); 
begin 
    if Assigned(FPanel) then 
    begin 
    ... 
    end; 
end; 

Non dimenticare di rimuovere le variabili locali da Button1Click e utilizzare i campi invece.

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    FPanel := TPanel.Create(Self); 
    ... 
end; 
+0

Questo ha fatto il trucco David. Ora dovrò solo studiare come questo può influenzare poche altre cose come, una serie di tpanel, ecc. Grazie mille! –

+0

@DimitrisNats Gli array di controlli vengono gestiti in modo simile. Hai solo bisogno di un campo della tua classe del tipo appropriato, ad es. 'FPanel: array di TPanel'. –

4

Anche se la risposta di David è anche molto corretta, ho pensato di prendere un momento ed entrare in ulteriori dettagli. A quanto sembra, sembra che tu sia molto nuovo con Delphi. C'è un problema molto comune con i principianti, che David non affronta nella sua risposta, relativo alla creazione e alla liberazione di questi oggetti. Ogni volta che chiami "Crea" in una classe, ad un certo punto, quando hai finito, devi anche "Liberare" quella classe. La mancata liberazione di qualcosa comporterà una perdita di memoria e nessuno la vorrà. Liberare è semplice quanto creare - finché non si entra nel tema di tenere una lista di oggetti (di cui non hai bisogno in questo momento).

Supponiamo di voler creare una casella di testo (TEdit) e posizionarla al centro del modulo. Ora, prima di tutto, l'IDE Delphi ti consente di rilasciare semplicemente questi controlli nel modulo, assicurandoti solo che tu lo sappia. Non devi necessariamente crearli/liberarli da soli, a meno che non ci sia uno scenario speciale. Ma farlo è pericoloso. Per questo esempio, supponiamo che questo controllo TEdit sarà lì per l'intera durata della tua applicazione.

In primo luogo, è necessario dichiarare una variabile da qualche parte per questo controllo. Il posto più ragionevole per questo è all'interno della classe in cui verrà utilizzato (in questo caso, il modulo che chiameremo Form1). Quando lavori con variabili (anche Fields) nel tuo modulo, assicurati di non mettere nulla sopra la sezione private. Tutto sopra private è inteso per codice generato automaticamente da Delphi per tutto ciò che è stato rilasciato (ed è visivo) nel modulo. In caso contrario, qualsiasi elemento creato manualmente deve passare a private o a public. L'area public sarebbe un buon posto per il vostro controllo ...

type 
    TForm1 = class(TForm) 
    private 

    public 
    MyEdit: TEdit; 
    end; 

Ora che è dichiarato, dobbiamo creare (e gratuito) di esso. È una buona pratica che ogni volta che crei qualcosa, che tu inserisca immediatamente il codice per liberarlo prima di continuare a lavorare. Crea un gestore di eventi per gli eventi OnCreate e OnDestroy del tuo modulo ...

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    MyEdit:= TMyEdit.Create(nil); 
    MyEdit.Parent:= Self; 
    MyEdit.Left:= (ClientWidth div 2) - (Width div 2); 
    MyEdit.Top:= (ClientHeight div 2) - (Height div 2); 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    if assigned(MyEdit) then MyEdit.Free; 
end; 

Se non si crea l'oggetto (prima creazione o dopo la distruzione), allora si otterrà un "violazione di accesso" quando si tenta di usarla. Questo perché l'applicazione tenta di accedere a un'area della memoria del computer che non è allocata o non corrisponde al tipo che si intende ottenere.

Bene, questo è il punto di partenza per sistemare il tuo scenario. Comunque un'altra cosa da mostrarti. Supponiamo che tu debba semplicemente creare un oggetto per un breve periodo, per la durata di una procedura. C'è un approccio diverso per questo. Nel tuo codice sopra, hai dichiarato la tua variabile direttamente all'interno della procedura. Questo esempio mostra quando è necessario farlo ...

procedure TForm1.Button1Click(Sender: TObject); 
var 
    MyObject: TMyObject; 
begin 
    MyObject:= TMyObject.Create; 
    try 
    MyObject.DoSomething; 
    Caption:= MyObject.GetSomething; 
    finally 
    MyObject.Free; 
    end; 
end; 

Vedete, finché MyObject saranno utilizzati solo in questo una chiamata a questa procedura, quindi è possibile dichiarare qui. Ma se ci si aspetta che l'oggetto rimanga in memoria dopo che questa procedura è terminata, allora le cose si complicheranno. Di nuovo, nel tuo caso, continua a metterlo nella classe del form fino a quando non avrai più familiarità con la creazione dinamica di oggetti.

Una nota finale, come già detto, consente di posizionare il controllo TEdit direttamente sul modulo in fase di progettazione senza scrivere il proprio codice. Se lo fai, ricorda di NON provare a creare o liberare questi. Questo è anche il caso in cui Delphi inserirà automaticamente il codice sopra la sezione private - è quando c'è qualcosa con cui non dovresti giocare.

+0

@downvoter per favore spiega cosa ho fatto di sbagliato e lo aggiusterò. –

+0

Buone informazioni - Ho upvoted. –

+2

@Jerry Non sono il downvoter ma penso che ciò che ti è mancato è che tutti i costruttori passano 'Self' come parametro' Owner'. Ciò significa che questi oggetti saranno tutti distrutti quando il modulo viene distrutto. –

2

Non penso di essere idoneo a "commentare", quindi sto definendo questo come una "risposta". Se si desidera ridimensionare i componenti runtime quando il genitore modifica le dimensioni, dare un'occhiata alla proprietà Anchors. Può farti risparmiare un sacco di lavoro.