1 pièce(s) jointe(s)
Problème de Pointer dans TList
Bonjour,
Je réfléchis à la possibilité de gérer des données par l'intermédiaire d'un TList qui manipule des pointeurs...
Je me heurte à un problème d'affectation d'un pointeur dans une procédure.
J'ai créé une Liste d'Objets Céleste dont voici le code.
Précision : je suis parti d'un exemple que j'avais en Delphi, j'ai converti le projet avec le menu Outils|Conversion Delphi|Convertir un projet Delphi en projet Lazarus. J'ai donc la directive de compilation suivante en début de chaque unité : {$MODE Delphi} ! Mais je ne pense pas que cela change quelque chose pour mon problème!
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
Type
{Champ des données du Catalogue des étoiles}
PListeObjets = ^TObjetsCelestes;
TObjetsCelestes =
Record
elNom :String[22];
elCooGalX : Integer;
elCooGalY : Integer;
elCooGalZ : Integer;
End;
...
var
Form1 : TForm1;
Liste : TList;
implementation
uses Unit2;
{$R *.lfm}
{==============================================================================}
{--- Initialisation du catalogue ------------------}
procedure TForm1.FormCreate(Sender: TObject);
begin
Liste := TList.Create; // Création de la liste
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Form1.btnToutSupprimerClick(nil);
Liste.Free;
end;
{--- Transfert les Saisies de la Fiche Form2 vers le Buffer des Objets de la Liste
-------------------------------------------------------------------------------}
procedure TForm1.SaisieFicheToRecord(aObjet : PListeObjets);
begin
With aObjet^ Do With Form2 do
begin
elNom := edNom.Text;
elCooGalX := edX.Value;
elCooGalY := edY.Value;
elCooGalZ := edZ.Value;
end;
end;
{--- Affichage des Objets Célestes du Catalogue dans une ListBox --------------}
Procedure TForm1.MAJAfficheListe;
Var i:Integer;
Begin
ListBox1.Items.Clear;
With Liste Do For i:=0 To Count-1 Do
if Items[i] = nil
then ListBox1.Items.Add('< liste vide >')
else With TObjetsCelestes(Items[i]^)
Do ListBox1.Items.Add(Format('%-20s%5d%5d%5d',[elNom,elCooGalX,elCooGalY,elCooGalZ]));
lbNombre.Caption := IntToStr(Liste.Count);
End;
{--- Ajoute un Objet Céleste ---------------------------------------------------
-------------------------------------------------------------------------------}
procedure TForm1.btnAjouterClick(Sender: TObject);
Var Objet : PListeObjets;
begin
{Valeurs par défaut}
With Form2 do
begin
edNom.Text := 'Nouveau Objet Céleste';
edX.Value := 100;
edY.Value := -200;
edZ.Value := 300;
end;
{Affichage saisie nouveau Objet Céleste: étoile, galaxie, planète...}
if Form2.ShowModal <> mrOK then Exit;
{Création nouveau objet céleste dans Liste}
New(Objet);
SaisieFicheToRecord(Objet);
Liste.Add(Objet);
{Mise a jour Affichage}
MAJAfficheListe;
end;
{--- Modifie un Objet Céleste --------------------------------------------------
-------------------------------------------------------------------------------}
procedure TForm1.btnModifierClick(Sender: TObject);
var Objet : PListeObjets;
begin
if ListBox1.ItemIndex < 0 then Exit;
{Test si l'objet Céleste n'est pas vide (nil) }
if Liste.Items[ListBox1.ItemIndex] = nil then Exit;
{Affichage de ses données et valeurs}
With TObjetsCelestes(Liste.Items[ListBox1.ItemIndex]^) Do
With Form2 do
begin
edNom.Text := elNom;
edX.Value := elCooGalX;
edY.Value := elCooGalY;
edZ.Value := elCooGalZ;
end;
{Demande de modification de l'objet Céleste}
if Form2.ShowModal <> mrOK then Exit;
{Mise à jour des valeurs}
With TObjetsCelestes(Liste.Items[ListBox1.ItemIndex]^) Do SaisieFicheToRecord(Objet);
{ With TObjetsCelestes(Liste.Items[ListBox1.ItemIndex]^)Do
With Form2 do
Begin
elNom := edNom.Text;
elCooGalX := edX.Value;
elCooGalY := edY.Value;
elCooGalZ := edZ.Value;
End;
}
{Mise a jour Affichage dans LisBox}
MAJAfficheListe;
end; |
Unit2 est juste une fiche modale ne comprenant aucune ligne de code pour la saisie des données :
Pièce jointe 654830
La liste se crée et s'affiche correctement dans la ListBox.
Le problème se trouve quand je veux modifier une valeur dans un Objet choisi dans la ListBox.
L'instruction en rouge Plante car Objet n'est pas affecté du Pointeur qui est en relation avec l'affichage des valeurs de l'Objet que l'on veut afficher.
Si je remplace l'instruction SaisieFicheToRecord(Objet); par son équivalent en Vert, ça marche. Cela confirme que Objet passé en paramètre n'est pas initialisé, mais je n'arrive pas à le faire...
Je tourne en rond et ne parviens pas à trouver la méthode pour affecter la valeur du pointeur de l'objet affiché !
Est-ce que quelqu'un a une idée ?
Je posterais ensuite le code dans son ensemble car j'ai testé d'autres possibilités qui fonctionnent.
;)Merci
Classe générique de listes
Citation:
Envoyé par
Jlmat
Ok Valid, merci
je suis d'accord, c'est pas très propre de mélanger les Freemem et les New!
j'étais justement en train de réfléchir à créer une class spécialement pour gérer la TList.
d'autant qu'il faut que je puisse gérer des Double, ce qui complique un peu, mais ça sera un prochain post, si je n'y arrive pas...
J'ai essayé ton code et j'y ai appris des choses en particulier sur les notifications.
Finalement dans cette encapsulation, le compilateur n'a rien à redire, ça marche bien!
Merci
Classe générique de listes
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
// liste générique (fonctionne très bien)
{ TListeSimple }
// Exceptions
type EUndefinedFunctionProj = class(Exception);
type TListeSimple<T> = class(TFPList)
private
public
procedure ClearListe();
function GetNbElements(): integer; inline;
procedure InsertElement(const Idx: integer; const E: T);
procedure AddElement(const E: T); // et Rros Minet
function GetFirstElement(): T; inline;
function GetElement(const Idx: integer): T; inline;
function GetLastElement(): T; inline;
procedure PutElement(const Idx: integer; const E: T); inline;
function RemoveElement(const Idx: integer): boolean;
function RemoveLastElement(): boolean;
procedure EnQueue(const E: T); inline; // file: Ajoute un entrant -- Synonyme de procedure AddElement();
function DeQueue(): T; // file: extrait et supprime le premier entré (l'élément 0 est devant le guichet)
procedure Push(const E: T); inline; // Pile: Ajoute un élément -- Synonyme de AddElement()
function Pop(): T; // Pile: Extrait le dernier élément entré et le supprime de la liste
procedure Compacter();
end;
implementation
implementation
uses
Dialogs,
DGCDummyUnit; // Anti-erreur 'Fin du conde source non trouvée'
{ TListeSimple<T> }
procedure TListeSimple<T>.ClearListe();
var
i, n: Integer;
begin
n := self.Count;
if (n > 0) then
begin
for i := Count-1 downto 0 Do
begin
if (self.Items[i] <> Nil) then Dispose(self.Items[i]); // Libération
self.Delete(i); // Suppression de l'élément
end;
self.clear;
end;
end;
function TListeSimple<T>.GetNbElements(): integer;
begin
Result := self.Count;
end;
procedure TListeSimple<T>.InsertElement(const Idx: integer; const E: T);
var pE: ^T;
begin
New(pE);
pE^ := E;
self.Insert(Idx, pE);
end;
procedure TListeSimple<T>.AddElement(const E: T);
var pE: ^T;
begin
New(pE);
pE^ := E;
self.Add(pE);
end;
function TListeSimple<T>.GetFirstElement(): T;
begin
Result := T(Items[0]^);
end;
function TListeSimple<T>.GetElement(const Idx: integer): T;
begin
Result := T(Items[Idx]^);
end;
procedure TListeSimple<T>.PutElement(const Idx: integer; const E: T);
begin
try
if (Idx < 0) then exit;
T(Items[Idx]^) := E;
except
end;
end;
function TListeSimple<T>.RemoveElement(const Idx: integer): boolean;
begin
Result := False;
try
Dispose(self.Items[Idx]);
self.Delete(Idx);
Result := True;
except
end;
end;
function TListeSimple<T>.RemoveLastElement(): boolean;
var
Nb: Integer;
begin
Nb := self.Count;
if (0 = Nb) then Exit(false);
result := self.RemoveElement(Nb - 1);
end;
procedure TListeSimple<T>.EnQueue(const E: T);
begin
AddElement(E);
end;
function TListeSimple<T>.DeQueue(): T;
begin
Result := GetElement(0);
RemoveElement(0);
end;
procedure TListeSimple<T>.Push(const E: T);
begin
AddElement(E);
end;
function TListeSimple<T>.Pop(): T;
var
n: Integer;
begin
n := GetNbElements();
if (n > 0) then
begin
Result := GetElement(n-1);
RemoveElement(n-1);
end;
end;
procedure TListeSimple<T>.Compacter();
begin
self.Pack();
end;
function TListeSimple<T>.GetLastElement(): T;
var n: integer;
begin
n := self.getNbElements();
result := self.getElement(n-1);
end; |
Dérivation de la classe: Exemple avec des points 3D
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
type TPoint3Df = record
X: double;
Y: double;
Z: double;
end;
type TListePoints3Df = class(TListeSimple<TPoint3Df>)
private
public
end; |
Utilisation:
Code:
1 2 3 4 5 6 7 8 9
|
var
P: TPoint3df;
LS: TListePoints3Df;
begin
LS := TListePoints3Df .Create;
P.X := 403460.0; P.Y := 3089600.0 ; P.Z := 540.0;
LS.AddElement(P); |