Problème destruction tableau dynamique de composants

Résolu
cs_OhAime Messages postés 18 Date d'inscription vendredi 8 avril 2005 Statut Membre Dernière intervention 7 avril 2007 - 15 juil. 2006 à 04:57
cs_OhAime Messages postés 18 Date d'inscription vendredi 8 avril 2005 Statut Membre Dernière intervention 7 avril 2007 - 15 juil. 2006 à 16:36
Bonjour,

En fait j'ai créer un tableau dynamique de composants TEdit, et lors de l'appui sur un bouton, je souhaites que les composants soient détruits! Voilà mon code:

procedure TForm2.Stop(Sender: TObject);
var
i : integer;
begin
for i:= 0 to Length(Edit) do
begin
Edit[i].free;
end;
SetLength(Edit,0);
end;

Lorsque je met ce code pour la destruction, eh bien j'ai une erreur: Opération de pointeur incorrect.
J'ai essayer divers trucs, et j'ai donc remarqué que c'est uniquement lorsque qu'il essaye de détruire le premier composants du tableau! il peut supprimer tous les autres sans problème mais pas le premier...
Est-ce que vous sauriez pourquoi il fait ça?!

Merci d'avance

15 réponses

japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
15 juil. 2006 à 16:19
Ce code fonctionne parfaitement, y compris la création des 2 tableaux dans la même boucle.
Le problème vient d'ailleurs.
Moi, je n'aurais pas placé ce code dans l'évènement OnActivate du Form : c'est une source d'emm...s.
Par exemple, si tu "fermes" Form2 (hide) et que tu l'actives à nouveau, je t'explique pas...
3
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
15 juil. 2006 à 10:07
Salut,
essaye comme ceci :

procedure TForm2.Stop(Sender: TObject);
var
i : integer;
begin
for i:= Low(Edit) to High(Edit) do
...

@+
Cirec
0
DeltaFX Messages postés 449 Date d'inscription lundi 19 avril 2004 Statut Membre Dernière intervention 8 avril 2009 2
15 juil. 2006 à 10:35
Faut les détruire dans l'ordre inverse de création, donc
for i:= High(Edit) downtoLow(Edit) do
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
15 juil. 2006 à 11:09
Salut DeltaFX,

pourrais-tu préciser pourquoi "Faut les détruire dans l'ordre inverse de création" ?

Que je commence par  le premier où le dernier il n'y a pas de différence.

Donc si je suis ta logique et je fait :

SetLength(Edit, 10);
For I := 9 Downto 0 Do
Begin
  Edit[I] : = TEdit.Create(Self);
  ...
End;

Je vais devoir les détruires comme ceci :

For I := 0 to 9 Do
  Edit[I].Free;  ???????????????????????????????????????

Le problème de OhAime c'est qu'il à utilisé Length(Edit) au lieu de High(Edit) où encore Length(Edit) - 1
 ce qui provoque fatalement une Opération de Pointeur Incorrect
Length(Edit) : = 10

@+
Cirec
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_OhAime Messages postés 18 Date d'inscription vendredi 8 avril 2005 Statut Membre Dernière intervention 7 avril 2007
15 juil. 2006 à 14:58
J'ai essayer vos propositions, mais aucune ne fonctionne, j'ai toujours la même erreur. Lorsque j'essaye de les détruire à l'envers, c'est le dernier créer qui reste et me met l'erreur, sinon dans le même ordre que la création, le premier disparait, affiche l'erreur, et les autres restes ...

Je vous met le code de la création des compo, peut-être ais-je fait une erreur là...

var
  Form2: TForm2;
  Edit : Array of TEdit;
  Button : TButton;
  GB : TGroupBox;

procedure TForm2.FormActivate(Sender: TObject);
var
  i : integer;
begin

GB := TGroupBox.Create(Form2); {création d'une groupbox}
GB.Parent := Form2;
GB.Height := 25+(NbrPoints*25);
GB.Width := 200;
GB.Caption := 'test';
GB.Left := 40;

Button := TButton.Create(Form2); {création du boutton pour détruire les composants}
Button.Parent := Form2;
Button.Top := 20+(NbrPoints*25);
Button.OnClick := Form2.Stop;

SetLength(Edit,NbrPoints -1);

for i := 0 to NbrPoints -1 do  {création des TEdit, NbrPoints est une variable provenant d'une autre fiche.}
   begin
      Edit[i] := TEdit.Create(GB);
      Edit[i].Parent := GB;
      Edit[i].Name := 'PT'+IntToStr(i);
      Edit[i].Top := 20+(i*25);
      Edit[i].Width := 60;
      Edit[i].Left := 10;
   end;

Merci
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
15 juil. 2006 à 15:11
Salut,

"SetLength(Edit,NbrPoints -1);"

Là, j'aurais plutôt mis :

SetLength(Edit,NbrPoints);

Bonne prog' 
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
15 juil. 2006 à 15:21
D'ailleurs, pour  bien voir la différence, ou pour être sûr qu'il n'y aura pas d'erreur, tu peux laisser le reste du code tel quel, et remplacer :

"for i := 0 to NbrPoints -1 do"

par :

for i := 0 to High(Edit) do
0
cs_OhAime Messages postés 18 Date d'inscription vendredi 8 avril 2005 Statut Membre Dernière intervention 7 avril 2007
15 juil. 2006 à 15:29
Eh bien j'y avais pensé, j'avais essayer, et ça ne résoud toujours pas le problème ...
J'comprends plus rien moi! lol!!

J'vais tout remettre a plat, et réessayer!
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
15 juil. 2006 à 15:30
Salut cirec, salut DeltaFX,

Il aurait été indispensable de libérer du dernier au premier Edit si on avait opéré de cette manière :

    
procedure TForm1.FreeAllEdits;
var i: Integer;
begin
  for i := ComponentCount - 1 downto 0 do
    if Components[i] is TEdit then
      Components[i].Free;
  end;
end;

Mais il est possible qu'il soit plus élégant, voire efficace (question d'empilage, dépilage...) de libérer d'abord ce que l'on a créé en dernier ? La question reste posée...

Bonne prog'

japee
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
15 juil. 2006 à 15:51
Il y a un  "end" en trop dans mon code précédent...

OhAime, j'ai testé ton code, avec la modification que je t'ai suggérée.
Chez moi, ça marche.

Voici un bête copier-coller, j'ai juste remplacé TForm2 par TForm1, et modifié où c'est indiqué :

unit Unit1;



interface



uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;



type
  TForm1 = class(TForm)
    Edit1: TEdit;
    procedure FormActivate(Sender: TObject);
  private
    { Déclarations privées }
    procedure Stop(Sender: TObject);
  public
    { Déclarations publiques }
  end;



var
  Form1: TForm1;
  Edit : Array of TEdit;
  Button : TButton;
  GB : TGroupBox;



const NbrPoints = 15;





implementation



{$R *.DFM}



procedure TForm1.Stop(Sender: TObject);
var
  i : integer;
begin
  for i:= 0 to High(Edit)  do
  begin
    Edit[i].free;
  end;
  SetLength(Edit,0);
end;





procedure TForm1.FormActivate(Sender: TObject);
var
  i : integer;
begin



  GB := TGroupBox.Create(Form1);
  GB.Parent := Form1;
  GB.Height := 25+(NbrPoints*25);
  GB.Width := 200;
  GB.Caption := 'test';
  GB.Left := 40;



  Button := TButton.Create(Form1);
  Button.Parent := Form1;
  Button.Top := 20+(NbrPoints*25);
  Button.Left := 320;
  Button.OnClick := Form1.Stop;



  SetLength(Edit,NbrPoints);  //  <- modifié ici



  for i : = 0 to NbrPoints -1 do
  begin
    Edit[i] := TEdit.Create(GB);
    Edit[i].Parent := GB;
    Edit[i].Name := 'PT'+IntToStr(i);
    Edit[i].Top := 20+(i*25);
    Edit[i].Width := 60;
    Edit[i].Left := 10;
  end;
end;





end.


Bonne prog'
0
cs_OhAime Messages postés 18 Date d'inscription vendredi 8 avril 2005 Statut Membre Dernière intervention 7 avril 2007
15 juil. 2006 à 15:58
Alors en fait, j'ai à peu près résolu la chose!! J'avais enlever un peu de code pensant que ce n'était pas ça qui posait problème mais finalement c'était ça!! Voilà le code:

procedure TForm2.FormActivate(Sender: TObject);
var
  i : integer;
begin
GB := TGroupBox.Create(Form2);
GB.Parent := Form2;
GB.Height := 25+(NbrPoints*25);
GB.Width := 200;
GB.Caption := 'test';
GB.Left := 40;


Button := TButton.Create(Form2);
Button.Parent := Form2;
Button.Top := 20+(NbrPoints*25);
Button.OnClick := Form2.Stop;


SetLength(Edit,NbrPoints);
SetLength(EditDist,NbrPoints);

for i := 0 to High(Edit) do   { je rempli deux tableau de TEdit dans la même boucle }
   begin
      Edit[i] := TEdit.Create(Self);
      Edit[i].Parent := GB;
      Edit[i].Name := 'PT'+IntToStr(i);
      Edit[i].Top := 20+(i*25);
      Edit[i].Width := 60;
      Edit[i].Left := 10;


      EditDist[i] := Tedit.create(Self);
      EditDist[i].Parent := GB;
      EditDist[i].Name := 'Dist'+IntToStr(i);
      EditDist[i].top := 20+(i*25);
      EditDist[i].Width := 60;
      EditDist[i].Left := 80;


   end;
end;




procedure TForm2.Stop(Sender: TObject);
var
i : integer;
begin
for i:= Low(Edit) to High(Edit) do
begin
Edit[i].free;
end;
SetLength(Edit,0);
end;

***

Donc ça ne fonctionne pas quand je rempli les deux tableaux dans la même boucle! Si je met deux boucle l'une après l'autre, ça fonctionne, est-ce que vous en connaitriez la raison?!!

Merci pour tout en tout cas!
0
cs_OhAime Messages postés 18 Date d'inscription vendredi 8 avril 2005 Statut Membre Dernière intervention 7 avril 2007
15 juil. 2006 à 16:27
lol! c'est justement quand j'ai vu la m.... que ça mettait lorsque je fermais et réouvrai que j'ai penser à les détruire!!  Mais chez toi le code fonctionne??? Moi ça ne fonctionne pas!
0
cs_OhAime Messages postés 18 Date d'inscription vendredi 8 avril 2005 Statut Membre Dernière intervention 7 avril 2007
15 juil. 2006 à 16:30
Ah ben nan, finalement ça fonctionne!! Je comprend plus la! ça fonctionnait pas y'a 10 minutes! lol! Bon ben l'essentiel c'est que ça fonctionne!

Merci encore à tous!!
0
DeltaFX Messages postés 449 Date d'inscription lundi 19 avril 2004 Statut Membre Dernière intervention 8 avril 2009 2
15 juil. 2006 à 16:34
Ben primo ta procedure stop ne purge que Edit, t'as oublié EditDist et concernant ton remplissage , pitet me goure-je, mais bien que Edit et EditDist aient le meme nombre d'élément, utiliser High(Edit) comme limite d'index supérieure pour EditDist, c'est MAL !.

Faut voir ca dans la meme optique que la structure With :
With monTruc Do la salade_interne_a_MonTruc.

Ben là c'est pareil, quand tu appelles High  et Low sur un tableau, la logique veut que tu n'utilises ces bornes que pour le tableau en question, et pas pour un autre.

Donc deux boucles. (Ca changeras rien niveau temps CPU comsommé)

Mais tu peux aussi écrire
for i := 0 to NbrPoints do
begin
    tripote Edit[i];
    tripote EditDist[i];
end;
auxquel cas c'est a toi d'etre sur du nombre d'élément.
0
cs_OhAime Messages postés 18 Date d'inscription vendredi 8 avril 2005 Statut Membre Dernière intervention 7 avril 2007
15 juil. 2006 à 16:36
Ok! j'y penserait dorénavant! merci beaucoup !
0
Rejoignez-nous