Getter/Setter pour un TPersistent ? [Résolu]

Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 16 déc. 2010 à 05:36 - Dernière réponse : Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention
- 16 déc. 2010 à 23:02
Bonjour,
j'ai un petit problème avec les getters/setters d'une propriété de type TPersistent. Par exemple, avec le code suivant :

type
 TVector = class(TPersistent)
 private
  FX, FY: Double;
 published
  property X: Double read FX write FX;
  property Y: Double read FY write FY;
 end;

 TComposant = class(TComponent)
 private
  FVector: TVector;
 protected
  function GetVector: TVector;
  procedure SetVector(Value: TVector);
 public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;
 published
  property Vector: TVector read GetVector write SetVector;
 end;

constructor TComposant.Create(AOwner: TComponent);
begin
 inherited;
 FVector := TVector.Create;
end;

destructor TComposant.Destroy;
begin
 FVector.Free;
 inherited;
end;

function GetVector: TVector;
begin
 Result := FVector;
end;

procedure SetVector(Value: TVector);
begin
 FVector := Value;
end;


A priori ce code marche. Mais le problème, c'est que SetVector n'est appelé que si j'affecte directement la propriété de la façon suivante :

MonCompo.Vector := UnVector;


Par contre, si par exemple je fais

MonCompo.Vector.X := 5;


La valeur 5 n'est pas enregistrée, et rien ne se passe. Ceci est particulièrement pénible dans mon cas, car si j'ai choisi de dériver mon TVector d'un TPersistent, c'est pour qu'il s'affiche dans l'inspecteur d'objets comme un objet qu'on peut dérouler et l'on pourrait trouver les deux composantes du vecteur X et Y. Mais puisque l'inspecteur d'objets ne fait que des affectations du type MonCompo.Vector.X := unevaleur, rien ne se passe et ça ne sert à rien.

Je me disais qu'il existe peut-être une technique particulière, par exemple une méthode à surcharger du côté du TPersistent pour permettre ce genre de manipulations, mais je ne trouve aucune info ni dans l'aide de Delphi (qui, admettons-le, ne donne que des informations triviales), ni sur le net (des tutos très intéressants sur le TPersistent, certes, mais aucune information pertinente sur le problème que je rencontre). Je sollicite donc votre aide pour ce problème, car je ne souhaite pas avoir à laisser tomber l'idée du TPersistent et passer par deux propriétés différentes. Donc en fait ma question est : comment faire pour changer les propriétés d'un objet TPersistent de façon individuelle si celui-ci est lui-même une propriété d'un autre composant ? Comment gérer ce cas particulier ?

Merci d'avance pour votre aide .. et désolé pour le pâté

Cordialement, Bacterius !
Afficher la suite 

Votre réponse

8 réponses

Meilleure réponse
cs_yanb 260 Messages postés lundi 27 octobre 2003Date d'inscription 4 mars 2016 Dernière intervention - 16 déc. 2010 à 11:00
3
Merci
Salut,
je viens d'essayer Copier, Coller de ton code +
modification de tout à l'heure et installation composant.
resultat : fonctionnement correct
Le code complet
unit Vector;

interface

uses
  SysUtils, Classes;

type
 TVector = class(TPersistent)
 private
  FX, FY: Double;
 published
  property X: Double read FX write FX;
  property Y: Double read FY write FY;
 end;

 TComposant = class(TComponent)
 private
  FVector: TVector;
 protected
  function GetVector: TVector;
  procedure SetVector(Value: TVector);
 public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;
 published
  property Vector: TVector read GetVector write SetVector;
 end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Test', [TComposant]);
end;

constructor TComposant.Create(AOwner: TComponent);
begin
 inherited;
 FVector := TVector.Create;
end;

destructor TComposant.Destroy;
begin
 FVector.Free;
 inherited;
end;

function TComposant.GetVector: TVector;
begin
 Result := FVector;
end;

procedure TComposant.SetVector(Value: TVector);
begin
 FVector := Value;
end;
end.

Peut-être une erreur sur ton code complet...
@+yanb

Merci cs_yanb 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 89 internautes ce mois-ci

Commenter la réponse de cs_yanb
cs_yanb 260 Messages postés lundi 27 octobre 2003Date d'inscription 4 mars 2016 Dernière intervention - 16 déc. 2010 à 09:41
0
Merci
Salut,
au premier coup d'oeil peut-être un oublie en postant,
mais normalement je voie pas d'autres problèmes
function TComposant.GetVector: TVector;
begin
 Result := FVector;
end;

procedure TComposant.SetVector(Value: TVector);
begin
 FVector := Value;
end;

@+yanb
Commenter la réponse de cs_yanb
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 16 déc. 2010 à 10:10
0
Merci
Le code est correct. Mais c'est le comportement qui ne va pas. En images :

Avant de définir une composante du TVector (de type TPersistent) :



Au moment d'appuyer sur Entrée pour valider la nouvelle valeur :



Après avoir appuyé sur Entrée :



Je peux définir globalement le TPersistent mais je ne peux pas définir ses propriétés individuelles, et telle est ma question : comment faire ?

Cordialement, Bacterius !
Commenter la réponse de Bacterius
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 16 déc. 2010 à 11:15
0
Merci
Ah ... oui j'ai oublié de préciser. En fait le TVector serait plutôt contenu dans un TCollectionItem, et là ça ne marche plus. Mais là le code devient trop compliqué (plusieurs centaines de lignes). Enfin bon voilà, mais je pense que je vais faire différemment en fait, ça devient trop lourd à gérer. Merci de ton aide quand même Yanb.

PS : ce code sera posté sur DelphiFr quand il sera fini, vous n'allez pas être décus

Cordialement, Bacterius !
Commenter la réponse de Bacterius
cs_yanb 260 Messages postés lundi 27 octobre 2003Date d'inscription 4 mars 2016 Dernière intervention - 16 déc. 2010 à 12:11
0
Merci
ReSalut,
Avec TCollectionItem
J'ai peut-être oublié des trucs mais le plus gros est fait pour comparer
unit Vector;

interface

uses
  SysUtils, Classes;

type
    TVectorCollection = class;

    TVector = class(TPersistent)
    private
        FX, FY: Double;
    published
        property X: Double read FX write FX;
        property Y: Double read FY write FY;
    end;

    TComposant = class(TComponent)
    private
        FItems: TVectorCollection;
        procedure SetItems(Value:TVectorCollection);
    protected
    public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
    published
        property Vector: TVectorCollection read FItems write SetItems;
    end;

    TVectorItem = class(TCollectionItem)
    private
          FVector: TVector;
    protected
        function GetVector: TVector;
        procedure SetVector(Value: TVector);
        function GetDisplayName:String;override;
    public
        constructor Create(Collection: TCollection);override;
        destructor Destroy; override;
        procedure Assign(Source: TPersistent);override;
    published
        property Vector: TVector read GetVector write SetVector;
    end;

    TVectorCollection = class(TCollection)
    private
        FVector:TComposant;
        function GetItem(Index:integer):TVectorItem;
        procedure SetItem(Index:integer; Value:TVectorItem);
    Protected
        function GetOwner: TPersistent; override;
        procedure Update(Item:TCollectionItem);override;
    Public
        constructor Create(CVector:TComposant); virtual;
        destructor Destroy; override;
        function Add:TVectorItem;
        property Items[Index:Integer]:TVectorItem read GetItem write SetItem;default;
    end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Test', [TComposant]);
end;

constructor TVectorItem.Create(Collection:TCollection);
begin
    inherited Create(Collection);
    FVector := TVector.Create;
end;

destructor TVectorItem.Destroy;
begin
    inherited Destroy;
    FVector.Free;
end;

procedure TVectorItem.Assign(Source: TPersistent);
begin
    inherited Assign(Source);
end;

function TVectorItem.GetDisplayName: string;
begin
    Result := inherited GetDisplayName;
end;

function TVectorItem.GetVector: TVector;
begin
    Result := FVector;
end;

procedure TVectorItem.SetVector(Value: TVector);
begin
    FVector := Value;
end;

function TVectorCollection.GetItem(index: Integer):TVectorItem;
begin
    Result:=TVectorItem(inherited GetItem(index));
end;

procedure TVectorCollection.SetItem(index:Integer;Value:TVectorItem);
begin
    inherited SetItem(Index,Value);
end;

function TVectorCollection.GetOwner;
begin
    Result:=FVector;
end;

constructor TVectorCollection.create(CVector:TComposant);
begin
    inherited create(TVectorItem);
    FVector:=CVector;
end;

destructor TVectorCollection.Destroy;
begin
    inherited Destroy;
end;

function TVectorCollection.Add:TVectorItem;
begin
    Result:=TVectorItem(inherited Add);
end;

Procedure TVectorCollection.Update(Item :TCollectionItem);
begin
;
end;

Procedure TComposant.SetItems(Value: TVectorCollection);
begin
    FItems.Assign(Value);
end;

constructor TComposant.Create(AOwner: TComponent);
begin
    inherited;
    FItems := TVectorCollection.Create(Self);
end;

destructor TComposant.Destroy;
begin
    FItems.Free;
    inherited;
end;
end.

@+yanb
Commenter la réponse de cs_yanb
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 16 déc. 2010 à 12:55
0
Merci
Salut,

commence par mettre des setters pour les propriétés X et Y .. on sait jamais
avant de reprendre tout le code


[hr]@+Cirec
[hr]
Commenter la réponse de Cirec
Utilisateur anonyme - 16 déc. 2010 à 13:17
0
Merci
Salut,

Si malgré la remarque pertinente de Cirec cela ne fonctionne pas, ici tu as exemple de getter et setter avec des TCollections
Commenter la réponse de Utilisateur anonyme
Bacterius 3869 Messages postés samedi 22 décembre 2007Date d'inscription 3 juin 2016 Dernière intervention - 16 déc. 2010 à 23:02
0
Merci
Salut,
c'était bien le getter qui ne marchait pas et non pas le setter. Merci de votre aide !

Cordialement, Bacterius !
Commenter la réponse de Bacterius

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.