Difference between revisions of "Streaming components/fr"

From Free Pascal wiki
Jump to navigationJump to search
Line 152: Line 152:
 
</pre>
 
</pre>
  
== Writing your own component - Part 2 ==
+
== Inscriture de votre propre composant  - Partie  2 ==
  
Now the example can be extended and we can use arbitrary properties with only a few lines of code:
+
Maintenant l'exemple peut être prolongé et nous pouvons employer des propriétés arbitraires avec seulement quelques lignes de code :
 
<pre>
 
<pre>
 
type
 
type
Line 179: Line 179:
 
</pre>
 
</pre>
  
This component can now be saved, loaded or used by the
+
Ce composant peut maintenant être sauvegardé , chargé  ou utilisé par 
[[RTTI controls/fr|Les contrôles RTTI]]. You don't need to write any further code.
+
[[RTTI controls/fr|Les contrôles RTTI]]. Vous n'avez pas besoin d'écrire tout autre code .
  
 
== Writing and Reading components from/to XML ==
 
== Writing and Reading components from/to XML ==

Revision as of 23:07, 28 June 2007

Deutsch (de) English (en) français (fr) 日本語 (ja) polski (pl) português (pt)

Introduction

Normalement, quand vous voulez stocker des données sur le disque ou par le réseau, vous devez écrire le code pour le chargement et la sauvegarde de chaque propriété. Ce tutoriel décrit comment écrire des classes , cela peut être chargé et sauvé à partir de flux sans charge supplémentaire de code de chargement/sauvegarde en utilisant la RTTI.

Il y a un exemple dans les sources lazarus, démontrant comment enregistrer un TGroupBox avec un enfant TCheckBox vers un flux et lire le flux de nouveau pour créer une copie des deux composants .

 Voir <lazaruspath>/examples/componentstreaming/

En combination avec Les contrôles RTTI vous pouvez réduire la quantité de code nécessaire pour connecter les données du programme avec le GUI et le Disque/Réseau à un minimum .

TComponent / TPersistent

La classe TPersistent est définie dans l'unité Classes et utilise la directive du compilateur {$M+} . Cette directive dit au compilateur de créer de l'information pendant le temps d'exécution (RTTI). Ceci signifie que lui et tous ses descendants obtiennent une nouvelle section de classe published. les propriétés 'published' sont visibles comme 'public', mais additionnellement leur structure est accessible pendant le temps d'exécution . Cela signifie que toutes propriétés published peut être lu et écrite pendant le temps d'execution. L'IDE par exemple emploie ceci pour travailler avec des composants dont il n'a jamais entendus parler .

TComponent prolonge TPersistent by the ability to have child components. This is important for streaming, where one component is the root component also called lookup root with a list of child components.

TReader / TWriter

Ce sont les classes qui travaillent, qui lisent/écrivent un TComponent vers/depuis un flux (Voir CreateLRSReader et CreateLRSWriter). Elles emploient un Pilote pour lire /écrire un format spécial . En ce moment, il y a un lecteur(TLRSObjectReader), un writer (TLRSObjectWriter) pour le format d'objet binaire défini dans l'unité LResources et un writer (TXMLObjectWriter) pour TDOMDocument défini dans Laz_XMLStreaming. L'unité LResources contient également des fonctions pour convertir le format binaire en texte et l'inverse (LRSObjectBinaryToText, LRSObjectTextToBinary). La bibliothèque LCL préfère le codage UTF8 pour les chaînes de caractères, tandis que Delphi préfère Widestrings . Donc il y a également quelques fonctions de conversion.

Ecriture de votre propre composant - Partie 1

Un composant habituel peut être aussi simple que :

type
 TMyComponent = class(TComponent)
 private
   FID: integer;
 published
   property ID: integer read FID write FID;
 end;

Ecrire un composant sur un flux

L'unité LResources a une fonction pour cela :

 procedure WriteComponentAsBinaryToStream(AStream: TStream; AComponent: TComponent);

Il écrit un composant dans le format binaire sur le flux. Par exemple :

procedure TForm1.Button1Click(Sender: TObject);
var
  AStream: TMemoryStream;
begin
  AStream:=TMemoryStream.Create;
  try
    WriteComponentAsBinaryToStream(AStream,AGroupBox);
    ... save stream somewhere ...
  finally
    AStream.Free;
  end;
end;

Lecture d'un composant depuis un flux

L'unité LResources a une fonction pour cela :

 procedure ReadComponentFromBinaryStream(AStream: TStream;
   var RootComponent: TComponent; OnFindComponentClass: TFindComponentClassEvent; TheOwner: TComponent = nil);
  • AStream est le flux contenant un composant au format binaire.
  • RootComponent est soit un composant existant, dont les données seront écrasées, soit c'est nil et un nouveau composant sera créé.
  • OnFindComponentClass est une fonction, qui est utilisée par TReader pour obtenir la classe à partir des noms de classe dans le flux. Par exemple :
procedure TCompStreamDemoForm.OnFindClass(Reader: TReader;
  const AClassName: string; var ComponentClass: TComponentClass);
begin
  if CompareText(AClassName,'TGroupBox')=0 then
    ComponentClass:=TGroupBox
  else if CompareText(AClassName,'TCheckBox')=0 then
    ComponentClass:=TCheckBox;
end;
  • TheOwner est le propriétaire du composant , pendant la création d'un nouveau composant .

Propriétés pouvant être mise en flux

Il y a quelques limitations , sur les types TReader/TWriter qui peuvent être mis en flux:

  • Les types de base peuvent être mis en flux: les châines de caractère, integer, char, single, double, extended, byte, word, cardinal, shortint, les pointeurs de méthode, etc. .
  • TPersistent et ses descendants peuvent être mis en flux

Mise en flux de données courantes - DefineProperties.

Vous pouvez mettre en flux des données arbitraires additionelles en écrasant DefineProperties. Ceci permet de mettre en flux toutes les données , qui n'ont aucun type de base. Par exemple pour mettre en flux une variable FMyRect: TRect de votre composant , ajouter les trois méthodes suivantes à votre composant :

procedure DefineProperties(Filer: TFiler); override;
procedure ReadMyRect(Reader: TReader);
procedure WriteMyRect(Writer: TWriter);

Avec le code suivant :

procedure TMyComponent.DefineProperties(Filer: TFiler);
var
  MyRectMustBeSaved: Boolean;
begin
  inherited DefineProperties(Filer);
  MyRectMustBeSaved:=(MyRect.Left<>0)
                     or (MyRect.Top<>0)
                     or (MyRect.Right<>0)
                     or (MyRect.Bottom<>0);
  Filer.DefineProperty('MyRect',@ReadMyRect,@WriteMyRect,MyRectMustBeSaved);
end;

procedure TMyComponent.ReadMyRect(Reader: TReader);
begin
  with Reader do begin
    ReadListBegin;
    FMyRect.Left:=ReadInteger;
    FMyRect.Top:=ReadInteger;
    FMyRect.Right:=ReadInteger;
    FMyRect.Bottom:=ReadInteger;
    ReadListEnd;
  end;
end;

procedure TMyComponent.WriteMyRect(Writer: TWriter);
begin
  with Writer do begin
    WriteListBegin;
    WriteInteger(FMyRect.Left);
    WriteInteger(FMyRect.Top);
    WriteInteger(FMyRect.Right);
    WriteInteger(FMyRect.Bottom);
    WriteListEnd;
  end;
end;

Cela sauvegardera MyRect comme une propriété 'MyRect'.

Si vous mettez en flux beaucoup de TRect, alors vous ne voulez pas probablement écrire chaque fois ce code . L'unité LResources contient un exemple sur comment écrire une procédure pour définir une propriété rect :

 procedure DefineRectProperty(Filer: TFiler; const Name: string; ARect, DefaultRect: PRect);
 

De cette façon le code ci-dessus peut être écrit ainsi brièvement :

procedure TMyComponent.DefineProperties(Filer: TFiler);
begin
  inherited DefineProperties(Filer);
  DefineRectProperty(Filer,'MyRect',@FMyRect,nil);
end;

Inscriture de votre propre composant - Partie 2

Maintenant l'exemple peut être prolongé et nous pouvons employer des propriétés arbitraires avec seulement quelques lignes de code :

type
  TMyComponent = class(TComponent)
  private
    FID: integer;
    FRect1: TRect;
    FRect2: TRect;
  protected
    procedure DefineProperties(Filer: TFiler); override;
  public
    property Rect1: TRect read FRect1 write FRect1;
    property Rect2: TRect read FRect2 write FRect2;
  published
    property ID: integer read FID write FID;
  end;

procedure TMyComponent.DefineProperties(Filer: TFiler);
begin
  inherited DefineProperties(Filer);
  DefineRectProperty(Filer,'Rect1',@FRect1,nil);
  DefineRectProperty(Filer,'Rect2',@FRect2,nil);
end;

Ce composant peut maintenant être sauvegardé , chargé ou utilisé par Les contrôles RTTI. Vous n'avez pas besoin d'écrire tout autre code .

Writing and Reading components from/to XML

Streaming components is simple: See the example in lazarus/examples/xmlstreaming/.

Conclusion

RTTI est un mécanisme puissant, which can be used to easily stream whole classes and helps avoiding writing a lot of boring load/save code.

Voir également

Les contrôles RTTI