IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)



Comment créer dynamiquement un nombre d'objets non connu à l'avance ?
auteur : Geronimo
Le problème est qu'il faut garder trace des pointeurs pour pouvoir les utiliser et libérer la mémoire à la fin. Pour cela, il est possible d'utiliser la classe TList. La classe TList est une liste de pointeurs toute simple, avec un certains nombre de fonctions pour gérer cette liste. Dans l'exemple suivant, nous voulons créer un nouveau TLabel à chaque clic sur un bouton. Tout d'abord, il nous faut créer une TList. Placez donc la ligne suivante dans la classe Form1 de votre fichier en-tête :
TList *ListLabels;
Il nous faut ensuite construire cette liste, ce que nous faisons dans le constructeur de la fiche.
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    // Création dynamique de la liste
    ListLabels = new TList;
}
Ensuite, à chaque clic sur le bouton Button1, nous construisons un TLabel et nous ajoutons un pointeur sur celui-ci dans ListImages.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    // Demande le caption du nouveau TLabel
    AnsiString LabelCaption = InputBox("Nouveau TLabel", "Caption :", "");
    // Si jamais le caption a une longueur nulle, on quitte la fonction
    // (cela évite qu'un TLabel sans texte soit créé)
   if (!LabelCaption.Length())
        return;

    // Allocation du nouveau TLabel
    TLabel *Label = new TLabel(this);
    // Le parent du TLabel est la fiche courante (si on ne fait pas cette
    // initialisation, le TLabel ne s'affichera pas).
    Label->Parent = this;
    // On attribute la texte du TLabel
    Label->Caption = LabelCaption;
    // On le positionne sur la gauche
    Label->Left = 10;

    /* On veut maintenant que ce TLabel soit placé en-dessous des TLabels
       précédents, s'il y en a */

    if (ListLabels->Count) // Si la liste contient déjà des pointeurs
    {
        // On déclare un pointeur sur un TLabel
        TLabel* LabelPrecedent;
        // Et on lui attribue le pointeur convertit correspondant de la liste
        LabelPrecedent = (TLabel *)ListLabels->Items[ListLabels->Count-1];
        // Maintenant, on positionne le nouveau TLabel 20 pixels en-dessous du
        // haut de l'ancien.
        Label->Top = LabelPrecedent->Top + 20;
    }
    else // Si la liste est vide, notre TLabel est le premier et on le place
         // en haut
        Label->Top = 10;

    // Enfin, on ajoute un pointeur sur ce TLabel à la liste
    ListLabels->Add((void *)Label);

}
Il n'est pas nécessaire de détruire les TLabels, car ils sont automatiquement détruits par leur Owner (propriétaire). (cf l'intruction TLabel *Label = new TLabel(this); ou le this est le Owner). Mais il faut détruire les autres objets qui n'ont pas de Owner (vos classes, par exemple)
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
    //Destruction des TLabels
    //Ne pas mettre ces deux lignes pour des TLabel mais
    //mettez-les pour des classes qui n'ont pas de Owner.
    //for (int i=0; i ListImages-Count; i++)
    //   delete (TLabel*)ListLabels-Items[i];*/
  
    delete ListLabels;
}

On peut ensuite, si on le veut accéder à chaque TLabel par la syntaxe suivante, comme nous l'avons fait pour voir la position du Label précédent (cf plus haut) :
TLabel *Label;
Label = (TLabel *)ListLabels->Items[2]; // Accède au troisième TLabel
Attention, vérifiez toujours que vous n'essayez pas d'accèder à un TLabel non existant, auquel cas vous déclencheriez une violation d'accès. Si vous souhaitez plus de sécurité, utilisez les conteneurs standards de la STL que sont les vector s.

A lire également : l'article Créer dynamiquement une liste visuelle des images d'un répertoire