Criando componentes Delphi dinamicamente (em tempo de execução)

click fraud protection

Na maioria das vezes, ao programar no Delphi, você não precisa criar dinamicamente um componente. Se você soltar um componente em um formulário, o Delphi manipula a criação do componente automaticamente quando o formulário é criado. Este artigo abordará a maneira correta de criar componentes programaticamente em tempo de execução.

Criação dinâmica de componentes

Existem duas maneiras de criar componentes dinamicamente. Uma maneira é tornar um formulário (ou outro TComponent) o proprietário do novo componente. Essa é uma prática comum ao criar componentes compostos nos quais um contêiner visual cria e possui os subcomponentes. Isso garantirá que o componente recém-criado seja destruído quando o componente proprietário for destruído.

Para criar uma instância (objeto) de uma classe, chame seu método "Create". O construtor Create é um método de classe, em oposição a praticamente todos os outros métodos que você encontrará na programação Delphi, que são métodos de objetos.

Por exemplo, o TComponent declara o construtor Create da seguinte maneira:

instagram viewer

construtor Create (AOwner: TComponent); virtual;

Criação dinâmica com proprietários
Aqui está um exemplo de criação dinâmica, em que Auto é um descendente de TComponent ou TComponent (por exemplo, uma instância de um TForm):

com TTimer. Criar (Self) do
início
Intervalo: = 1000;
Ativado: = Falso;
OnTimer: = MyTimerEventHandler;
fim;

Criação dinâmica com uma chamada explícita para liberar
A segunda maneira de criar um componente é usar nada como o proprietário. Observe que, se você fizer isso, também deverá liberar explicitamente o objeto que criar, assim que não precisar mais dele (ou produzirá um vazamento de memória). Aqui está um exemplo do uso de nil como proprietário:

com TTable. Criar (nil) fazer
experimentar
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
Aberto;
Editar;
FieldByName ('Ocupado') .AsBoolean: = True;
Postar;
finalmente
Livre;
fim;

Criação dinâmica e referências a objetos
É possível aprimorar os dois exemplos anteriores, atribuindo o resultado da chamada Create a uma variável local ao método ou pertencente à classe. Isso geralmente é desejável quando referências ao componente precisa ser usado mais tarde, ou quando escopo problemas potencialmente causados ​​por blocos "Com" precisam ser evitados. Aqui está o código de criação do TTimer acima, usando uma variável de campo como referência ao objeto TTimer instanciado:

FTimer: = TTimer. Criar (Self);
com o FTimer do
início
Intervalo: = 1000;
Ativado: = Falso;
OnTimer: = MyInternalTimerEventHandler;
fim;

Neste exemplo, "FTimer" é uma variável de campo particular do formulário ou contêiner visual (ou o que seja "Self"). Ao acessar a variável FTimer a partir de métodos nesta classe, é uma boa idéia verificar se a referência é válida antes de usá-la. Isso é feito usando a função Assigned do Delphi:

se atribuído (FTimer), então FTimer. Ativado: = Verdadeiro;

Criação dinâmica e referências de objeto sem proprietários
Uma variação disso é criar o componente sem proprietário, mas manter a referência para destruição posterior. O código de construção para o TTimer ficaria assim:

FTimer: = TTimer. Criar (nulo);
com o FTimer do
início
...
fim;

E o código de destruição (presumivelmente no destruidor do formulário) ficaria assim:

FTimer. Livre;
FTimer: = nulo;
(*
Ou use o procedimento FreeAndNil (FTimer), que libera uma referência de objeto e substitui a referência por zero.
*)

Definir a referência do objeto como nulo é essencial ao liberar objetos. A chamada para Free primeiro verifica se a referência ao objeto é nula ou não e, se não for, chama o destruidor do objeto Destroy.

Criação dinâmica e referências de objeto local sem proprietários

Aqui está o código de criação TTable acima, usando uma variável local como referência ao objeto TTable instanciado:

localTable: = TTable. Criar (nulo);
experimentar
com localTable do
início
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
fim;
...
// Mais tarde, se queremos especificar explicitamente o escopo:
localTable. Aberto;
localTable. Editar;
localTable. FieldByName ('Ocupado') .AsBoolean: = True;
localTable. Postar;
finalmente
localTable. Livre;
localTable: = nulo;
fim;

No exemplo acima, "localTable" é um variável local declarado no mesmo método que contém esse código. Observe que, após liberar qualquer objeto, em geral, é uma boa idéia definir a referência como nula.

Uma palavra de aviso

IMPORTANTE: Não misture uma chamada para Free com a passagem de um proprietário válido para o construtor. Todas as técnicas anteriores funcionarão e são válidas, mas o seguinte deve nunca ocorre no seu código:

com TTable. Criar (auto) fazer
experimentar
...
finalmente
Livre;
fim;

O exemplo de código acima apresenta hits de desempenho desnecessários, afeta um pouco a memória e tem o potencial de apresentar bugs difíceis de encontrar. Descubra o porquê.

Nota: Se um componente criado dinamicamente tiver um proprietário (especificado pelo parâmetro AOwner do construtor Create), esse proprietário será responsável por destruir o componente. Caso contrário, você deverá ligar explicitamente para Free quando não precisar mais do componente.

Artigo originalmente escrito por Mark Miller

Um programa de teste foi criado no Delphi para cronometrar a criação dinâmica de 1000 componentes com contagens variáveis ​​de componentes iniciais. O programa de teste aparece na parte inferior desta página. O gráfico mostra um conjunto de resultados do programa de teste, comparando o tempo necessário para criar componentes, tanto com proprietários quanto sem proprietários. Observe que isso é apenas uma parte do acerto. Um atraso de desempenho semelhante pode ser esperado ao destruir componentes. O tempo para criar componentes dinamicamente com os proprietários é 1200% a 107960% mais lento que o tempo para criar componentes sem proprietários, dependendo do número de componentes no formulário e no componente que está sendo criada.

O Programa de Teste

Aviso: Este programa de teste não rastreia e libera componentes criados sem proprietários. Ao não rastrear e liberar esses componentes, os tempos medidos para o código de criação dinâmica refletem com mais precisão o tempo real para criar dinamicamente um componente.

Baixar código fonte

Atenção!

Se você deseja instanciar dinamicamente um componente Delphi e liberá-lo explicitamente algum tempo depois, sempre passe nulo como proprietário. Não fazer isso pode apresentar riscos desnecessários, além de problemas de desempenho e manutenção de código. Leia o artigo "Um aviso sobre a instanciação dinâmica de componentes Delphi" para saber mais ...

instagram story viewer