Sign in Join
Wiki copytemporary

Streaming components/de: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11Zurück zu den [[Additional information/de|Zusätzlichen Informationen]].\
22
33== Einleitung ==
44
55Normalerweise, wenn sie die Eigenschaftswerte eines Objekts speichern wollen, müssen sie Code schreiben für das Laden und Speichern jeder Eigenschaft. Dieses Tutorial beschreibt, wie man Klassen entwickelt, die ihre Eigenschaftswerte über einen Stream laden und speichern können ohne zusätzlichen Code dafür schreiben zu müssen. Dies geht unter Verwendung der RTTI.
66
77Es gibt ein Beispiel in den Lazarus Quelltexten, welches demonstriert, wie eine TGroupBox mit einer eingebetteten TCheckBox-Komponente über einen Stream gespeichert wird und durch lesen aus einem Stream neu erzeugt werden kann.
88
9-` Siehe <lazaruspath>/examples/componentstreaming/`
9+```text
10+ Siehe <lazaruspath>/examples/componentstreaming/
11+```
1012
1113In Kombination mit [[RTTI controls/de|RTTI Bedienelementen]] können sie den Umfang des Codes, der für das Verbinden der Programmdaten mit dem GUI und der Platte / dem Netzwerk benötigt wird, auf ein Minimum reduzieren.
1214
1315## TComponent / TPersistent
1416
1517Die Klasse **TPersistent** ist definiert in der Unit Classes und verwendet den Compilerschalter **{\$M+}**. Dieser Schalter veranlasst den Compiler, Laufzeit-Typinformationen (engl. Run Time Type Information, **RTTI**) zu erzeugen. Das bedeutet, die Klasse und alle ihre Nachfahren erhalten einen neuen Klassenabschnitt **published**. 'Published'-Eigenschaften sind sichtbar wie 'public', aber zusätzlich ist ihre Struktur zur Laufzeit erreichbar. Alle published-Eigenschaften können zur Laufzeit gelesen und geschrieben werden, ohne dass ihr Name bekannt sein muss, während das Programm geschrieben wird. Lazarus kann damit alle Komponenten verwenden, ohne dass für jede Komponente neuer Code geschrieben werden muss.
1618
1719**TComponent** erweitert TPersistent durch die Möglichkeit, child components zu haben. Das ist wichtig für das streaming, wo eine Komponente die **root component** auch **lookup root** genannt ist mit einer Liste (list) von Child-Komponenten.
1820
1921## TReader / TWriter
2022
2123Diese Klassen erledigen die Arbeit und schreiben/lesen ein TComponent in den/aus dem Stream. (siehe: CreateLRSReader und CreateLRSWriter). Sie benutzen einen **Driver**, um ein spezielles Format zu lesen/schreiben. Momentan gibt es einen reader (TLRSObjectReader) und einen writer (TLRSObjectWriter) für das binary object format in der unit LResources und einen writer (TXMLObjectWriter) für TDOMDocument in der unit Laz_XMLStreaming. Die LResources Unit enthält auch Funktionen, um das binäre Format in Text zu konvertieren und umgekehrt (LRSObjectBinaryToText, LRSObjectTextToBinary). Die LCL bevorzugt UTF8 für Strings, während Delphi Widestrings bevorzugt. Daher gibt es auch einige Konvertierungsfunktionen.
2224
2325## Schreiben ihrer eigenen Komponente - Teil 1
2426
2527Eine maßgeschneiderte Komponente kann so einfach sein wie:
2628
2729```delphi
2830
2931type
3032 TMyComponent = class(TComponent)
3133 private
3234 FID: integer;
3335 published
3436 property ID: integer read FID write FID;
3537 end;
3638```
3739
3840## Schreiben einer Komponente in einen Stream
3941
4042Die Unit [[doc:lcl/lresources|LResources]] hat eine Funktion dafür:
4143
4244```delphi
4345procedure WriteComponentAsBinaryToStream(AStream: TStream; AComponent: TComponent);
4446```
4547
4648Sie schreibt eine Komponente im binären Format in den Stream. Zum Beispiel:
4749
4850```delphi
4951procedure TForm1.Button1Click(Sender: TObject);
5052var
5153 AStream: TMemoryStream;
5254begin
5355 AStream:=TMemoryStream.Create;
5456 try
5557 WriteComponentAsBinaryToStream(AStream,AGroupBox);
5658 // ... Stream weiterverarbeiten oder abspeichern ...
5759 finally
5860 AStream.Free;
5961 end;
6062end;
6163```
6264
6365## Lesen einer Komponente aus einem Stream
6466
6567Die Unit LResources hat eine Funktion dafür:
6668
6769```delphi
6870procedure ReadComponentFromBinaryStream(AStream: TStream;
6971 var RootComponent: TComponent; OnFindComponentClass: TFindComponentClassEvent; TheOwner: TComponent = nil);
7072```
7173
7274- AStream ist der Stream, der eine Komponente im binären Format enthält.
7375- RootComponent ist entweder eine existierende Komponente, deren Daten überschrieben werden, oder ist null und eine neue Komponente wird erzeugt.
7476- OnFindComponentClass ist eine Funktion, die von TReader verwendet wird, um die Klasse aus den Klassennamen im Stream zu erhalten. Zum Beispiel:
7577
7678```delphi
7779procedure TCompStreamDemoForm.OnFindClass(Reader: TReader;
7880 const AClassName: string; var ComponentClass: TComponentClass);
7981begin
8082 if CompareText(AClassName,'TGroupBox')=0 then
8183 ComponentClass:=TGroupBox
8284 else if CompareText(AClassName,'TCheckBox')=0 then
8385 ComponentClass:=TCheckBox;
8486end;
8587```
8688
8789- TheOwner is the component owner, when creating a new component.
8890
8991## Streambare Eigenschaften
9092
9193Es gibt einige Einschränkungen, welche Typen TReader/TWriter streamen kann:
9294
9395- Basistypen können gestreamt werden: string, integer, char, single, double, extended, byte, word, cardinal, shortint, method pointers, etc. .
9496- TPersistent und Nachfahren können gestreamt werden
9597
9698- Records, Objekte und Klassen, die nicht von TPersistent abstammen, können nicht gestreamt werden. um sie zu streamen muss man TReader/TWriter mitteilen wie. Siehe unten #Streaming custom Data - DefineProperties.
9799
98100## Streaming custom Data - DefineProperties
99101
100102Sie können zusätzlich beliebige Daten streamen, indem Sie **DefineProperties** überschreiben(=override). So können Sie alle Daten streamen, die keine passenden Grund-Typen haben. Beispiel : um eine Variable **FMyRect: TRect** Ihrer Komponente zu überschreiben, fügen sie die folgenden drei Methoden zu ihrer Komponente hinzu:
101103
102104```delphi
103105procedure DefineProperties(Filer: TFiler); override;
104106procedure ReadMyRect(Reader: TReader);
105107procedure WriteMyRect(Writer: TWriter);
106108```
107109
108110mit dem folgenden Code:
109111
110112```delphi
111113procedure TMyComponent.DefineProperties(Filer: TFiler);
112114var
113115 MyRectMustBeSaved: Boolean;
114116begin
115117 inherited DefineProperties(Filer);
116118 MyRectMustBeSaved:=(MyRect.Left<>0)
117119 or (MyRect.Top<>0)
118120 or (MyRect.Right<>0)
119121 or (MyRect.Bottom<>0);
120122 Filer.DefineProperty('MyRect',@ReadMyRect,@WriteMyRect,MyRectMustBeSaved);
121123end;
122124
123125procedure TMyComponent.ReadMyRect(Reader: TReader);
124126begin
125127 with Reader do begin
126128 ReadListBegin;
127129 FMyRect.Left:=ReadInteger;
128130 FMyRect.Top:=ReadInteger;
129131 FMyRect.Right:=ReadInteger;
130132 FMyRect.Bottom:=ReadInteger;
131133 ReadListEnd;
132134 end;
133135end;
134136
135137procedure TMyComponent.WriteMyRect(Writer: TWriter);
136138begin
137139 with Writer do begin
138140 WriteListBegin;
139141 WriteInteger(FMyRect.Left);
140142 WriteInteger(FMyRect.Top);
141143 WriteInteger(FMyRect.Right);
142144 WriteInteger(FMyRect.Bottom);
143145 WriteListEnd;
144146 end;
145147end;
146148```
147149
148150Dies wird MyRect als Eigenschaft 'MyRect' speichern.
149151
150152Falls Sie oft TRect streamen , dann wollen sie wahrscheinlich nicht jedes Mal den ganzen Code schreiben.
151153
152154Die Unit LResources enthält ein Beispiel, wie man eine Prozedur schreibt, um eine rect Eigenschaft zu definieren:
153155
154156```delphi
155157procedure DefineRectProperty(Filer: TFiler; const Name: string; ARect, DefaultRect: PRect);
156158```
157159
158160Auf diese Art kann der obige Code kurz gehalten werden :
159161
160162```delphi
161163procedure TMyComponent.DefineProperties(Filer: TFiler);
162164begin
163165 inherited DefineProperties(Filer);
164166 DefineRectProperty(Filer,'MyRect',@FMyRect,nil);
165167end;
166168```
167169
168170## Schreiben ihrer eigenen Komponente - Teil 2
169171
170172Jetzt kann das Beispiel erweitert werden und wir können beliebige Eigenschaften verwenden mit nur ein paar Zeilen Code:
171173
172174```delphi
173175type
174176 TMyComponent = class(TComponent)
175177 private
176178 FID: integer;
177179 FRect1: TRect;
178180 FRect2: TRect;
179181 protected
180182 procedure DefineProperties(Filer: TFiler); override;
181183 public
182184 property Rect1: TRect read FRect1 write FRect1;
183185 property Rect2: TRect read FRect2 write FRect2;
184186 published
185187 property ID: integer read FID write FID;
186188 end;
187189
188190procedure TMyComponent.DefineProperties(Filer: TFiler);
189191begin
190192 inherited DefineProperties(Filer);
191193 DefineRectProperty(Filer,'Rect1',@FRect1,nil);
192194 DefineRectProperty(Filer,'Rect2',@FRect2,nil);
193195end;
194196```
195197
196198Diese Komponente kann nun gespeichert, geladen oder von den [[RTTI controls/de|RTTI Bedienelementen]] verwendet werden. Sie müssen keinen weiteren Code schreiben.
197199
198200## Writing and Reading components from/to LFM
199201
200202Beispiele finden Sie in der unit **lresources** : function ReadComponentFromTextStream und writeComponentAsTextToStream
201203
202204## Writing and Reading components from/to XML
203205
204206Streaming components ist einfach: Siehe das Beispiel in lazarus/examples/xmlstreaming/.
205207
206208## Fazit
207209
208210RTTI ist ein leistungsstarker Mechanismus, der verwendet werden kann, um einfach ganze Klassen zu streamen, und er hilft das Schreiben von langweiligem Laden/Speichern Code zu vermeiden.
209211
210212## Siehe auch
211213
212214- [[RTTI controls/de|RTTI controls]]
213215
214216---
215217*From the Free Pascal wiki, page "Streaming components/de", as it stood on 2014-05-07 after a change by Socke, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
216218Category: Components/de
217219Category: Deutsch
218220Category: Tutorials/de

Back to history