Création dynamique de composants Delphi (au moment de l'exécution)

Le plus souvent, lors de la programmation dans Delphi, vous n'avez pas besoin de créer dynamiquement un composant. Si vous déposez un composant sur une fiche, Delphi gère automatiquement la création du composant lors de la création de la fiche. Cet article couvrira la façon correcte de créer des composants par programme au moment de l'exécution.

Création de composants dynamiques

Il existe deux façons de créer dynamiquement des composants. Une façon consiste à faire d'un formulaire (ou d'un autre composant TComponent) le propriétaire du nouveau composant. Il s'agit d'une pratique courante lors de la création de composants composites dans lesquels un conteneur visuel crée et possède les sous-composants. Cela garantira que le composant nouvellement créé est détruit lorsque le composant propriétaire est détruit.

Pour créer une instance (objet) d'une classe, vous appelez sa méthode "Create". Le constructeur Create est un méthode de classe, contrairement à pratiquement toutes les autres méthodes que vous rencontrerez dans la programmation Delphi, qui sont des méthodes objet.

instagram viewer

Par exemple, le TComponent déclare le constructeur Create comme suit:

constructeur Create (AOwner: TComponent); virtuel;

Création dynamique avec les propriétaires
Voici un exemple de création dynamique, où Soi est un descendant de TComponent ou TComponent (par exemple, une instance d'un TForm):

avec TTimer. Créer (Soi) faire
commencer
Intervalle: = 1000;
Activé: = False;
OnTimer: = MyTimerEventHandler;
fin;

Création dynamique avec un appel explicite à la gratuité
La deuxième façon de créer un composant consiste à utiliser néant en tant que propriétaire. Notez que si vous faites cela, vous devez également libérer explicitement l'objet que vous créez dès que vous n'en avez plus besoin (ou vous produirez un fuite de mémoire). Voici un exemple d'utilisation de nil en tant que propriétaire:

avec TTable. Créer (néant) faire
essayer
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
Ouvert;
Éditer;
FieldByName ('Occupé'). AsBoolean: = True;
Publier;
enfin
Gratuit;
fin;

Création dynamique et références d'objets
Il est possible d'améliorer les deux exemples précédents en affectant le résultat de l'appel Create à une variable locale à la méthode ou appartenant à la classe. Cela est souvent souhaitable lorsque des références aux composant doivent être utilisés plus tard, ou lorsque cadrage les problèmes potentiellement causés par les blocs "Avec" doivent être évités. Voici le code de création TTimer ci-dessus, en utilisant une variable de champ comme référence à l'objet TTimer instancié:

FTimer: = TTimer. Créer (Soi);
avec FTimer do
commencer
Intervalle: = 1000;
Activé: = False;
OnTimer: = MyInternalTimerEventHandler;
fin;

Dans cet exemple, "FTimer" est une variable de champ privé du formulaire ou du conteneur visuel (ou quel que soit "Self"). Lorsque vous accédez à la variable FTimer à partir des méthodes de cette classe, c'est une très bonne idée de vérifier si la référence est valide avant de l'utiliser. Cela se fait à l'aide de la fonction affectée de Delphi:

si assigné (FTimer) puis FTimer. Activé: = True;

Création dynamique et références d'objets sans propriétaires
Une variante à cela consiste à créer le composant sans propriétaire, mais à conserver la référence pour une destruction ultérieure. Le code de construction du TTimer ressemblerait à ceci:

FTimer: = TTimer. Créer (néant);
avec FTimer do
commencer
...
fin;

Et le code de destruction (probablement dans le destructeur du formulaire) ressemblerait à ceci:

FTimer. Gratuit;
FTimer: = zéro;
(*
Ou utilisez la procédure FreeAndNil (FTimer), qui libère une référence d'objet et remplace la référence par nil.
*)

La définition de la référence d'objet sur nil est critique lors de la libération d'objets. L'appel à Free vérifie d'abord si la référence de l'objet est nulle ou non, et si ce n'est pas le cas, il appelle le destructeur de l'objet Destroy.

Création dynamique et références d'objets locaux sans propriétaires

Voici le code de création TTable ci-dessus, en utilisant une variable locale comme référence à l'objet TTable instancié:

localTable: = TTable. Créer (néant);
essayer
avec localTable do
commencer
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
fin;
...
// Plus tard, si nous voulons spécifier explicitement la portée:
localTable. Ouvert;
localTable. Éditer;
localTable. FieldByName ('Occupé'). AsBoolean: = True;
localTable. Publier;
enfin
localTable. Gratuit;
localTable: = nil;
fin;

Dans l'exemple ci-dessus, "localTable" est un variable locale déclaré dans la même méthode contenant ce code. Notez qu'après avoir libéré un objet, en général, c'est une très bonne idée de définir la référence sur nil.

Un mot d'avertissement

IMPORTANT: ne mélangez pas un appel à Free avec la transmission d'un propriétaire valide au constructeur. Toutes les techniques précédentes fonctionneront et sont valides, mais les suivantes devraient ne se produit jamais dans votre code:

avec TTable. Créer (soi) faire
essayer
...
enfin
Gratuit;
fin;

L'exemple de code ci-dessus introduit des résultats de performances inutiles, affecte légèrement la mémoire et a le potentiel d'introduire des bogues difficiles à trouver. J'ai trouvé pourquoi.

Remarque: Si un composant créé dynamiquement a un propriétaire (spécifié par le paramètre AOwner du constructeur Create), ce propriétaire est responsable de la destruction du composant. Sinon, vous devez explicitement appeler Free lorsque vous n'avez plus besoin du composant.

Article écrit à l'origine par Mark Miller

Un programme de test a été créé dans Delphi pour chronométrer la création dynamique de 1000 composants avec différents nombres de composants initiaux. Le programme de test apparaît au bas de cette page. Le graphique présente un ensemble de résultats du programme de test, comparant le temps nécessaire pour créer des composants avec ou sans propriétaire. Notez que ce n'est qu'une partie du hit. Un retard de performances similaire peut être attendu lors de la destruction de composants. Le temps pour créer dynamiquement des composants avec les propriétaires est de 1200% à 107960% plus lent que celui de créer composants sans propriétaires, selon le nombre de composants sur la forme et le composant étant créé.

Le programme de test

Avertissement: ce programme de test ne suit pas et ne libère pas les composants créés sans propriétaires. En ne suivant pas et en ne libérant pas ces composants, les temps mesurés pour le code de création dynamique reflètent plus précisément le temps réel pour créer dynamiquement un composant.

Télécharger le code source

Avertissement!

Si vous souhaitez instancier dynamiquement un composant Delphi et le libérer explicitement un peu plus tard, passez toujours nil en tant que propriétaire. Ne pas le faire peut entraîner des risques inutiles, ainsi que des problèmes de performances et de maintenance du code. Lisez l'article "Un avertissement sur l'instanciation dynamique des composants Delphi" pour en savoir plus ...

instagram story viewer