Sign in Join
Wiki copytemporary

Streaming components/de: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Streaming components/de

OldNewLine
1+\
2+Zurück zu den [[Additional information/de|Zusätzlichen Informationen]].\
3+\
4+\
5+== Einleitung ==
6+
7+Normalerweise, 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.
8+
9+Es 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.
10+
11+` Siehe <lazaruspath>/examples/componentstreaming/`
12+
13+In 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.
14+
15+## TComponent / TPersistent
16+
17+Die 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.
18+
19+**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.
20+
21+## TReader / TWriter
22+
23+Diese 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.
24+
25+## Schreiben ihrer eigenen Komponente - Teil 1
26+
27+Eine maßgeschneiderte Komponente kann so einfach sein wie:
28+
29+```delphi
30+
31+type
32+ TMyComponent = class(TComponent)
33+ private
34+ FID: integer;
35+ published
36+ property ID: integer read FID write FID;
37+ end;
38+```
39+
40+## Schreiben einer Komponente in einen Stream
41+
42+Die Unit [[doc:lcl/lresources|LResources]] hat eine Funktion dafür:
43+
44+```delphi
45+procedure WriteComponentAsBinaryToStream(AStream: TStream; AComponent: TComponent);
46+```
47+
48+Sie schreibt eine Komponente im binären Format in den Stream. Zum Beispiel:
49+
50+```delphi
51+procedure TForm1.Button1Click(Sender: TObject);
52+var
53+ AStream: TMemoryStream;
54+begin
55+ AStream:=TMemoryStream.Create;
56+ try
57+ WriteComponentAsBinaryToStream(AStream,AGroupBox);
58+ // ... Stream weiterverarbeiten oder abspeichern ...
59+ finally
60+ AStream.Free;
61+ end;
62+end;
63+```
64+
65+## Lesen einer Komponente aus einem Stream
66+
67+Die Unit LResources hat eine Funktion dafür:
68+
69+```delphi
70+procedure ReadComponentFromBinaryStream(AStream: TStream;
71+ var RootComponent: TComponent; OnFindComponentClass: TFindComponentClassEvent; TheOwner: TComponent = nil);
72+```
73+
74+- AStream ist der Stream, der eine Komponente im binären Format enthält.
75+- RootComponent ist entweder eine existierende Komponente, deren Daten überschrieben werden, oder ist null und eine neue Komponente wird erzeugt.
76+- OnFindComponentClass ist eine Funktion, die von TReader verwendet wird, um die Klasse aus den Klassennamen im Stream zu erhalten. Zum Beispiel:
77+
78+```delphi
79+procedure TCompStreamDemoForm.OnFindClass(Reader: TReader;
80+ const AClassName: string; var ComponentClass: TComponentClass);
81+begin
82+ if CompareText(AClassName,'TGroupBox')=0 then
83+ ComponentClass:=TGroupBox
84+ else if CompareText(AClassName,'TCheckBox')=0 then
85+ ComponentClass:=TCheckBox;
86+end;
87+```
88+
89+- TheOwner is the component owner, when creating a new component.
90+
91+## Streambare Eigenschaften
92+
93+Es gibt einige Einschränkungen, welche Typen TReader/TWriter streamen kann:
94+
95+- Basistypen können gestreamt werden: string, integer, char, single, double, extended, byte, word, cardinal, shortint, method pointers, etc. .
96+- TPersistent und Nachfahren können gestreamt werden
97+
98+- 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.
99+
100+## Streaming custom Data - DefineProperties
101+
102+Sie 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:
103+
104+```delphi
105+procedure DefineProperties(Filer: TFiler); override;
106+procedure ReadMyRect(Reader: TReader);
107+procedure WriteMyRect(Writer: TWriter);
108+```
109+
110+mit dem folgenden Code:
111+
112+```delphi
113+procedure TMyComponent.DefineProperties(Filer: TFiler);
114+var
115+ MyRectMustBeSaved: Boolean;
116+begin
117+ inherited DefineProperties(Filer);
118+ MyRectMustBeSaved:=(MyRect.Left<>0)
119+ or (MyRect.Top<>0)
120+ or (MyRect.Right<>0)
121+ or (MyRect.Bottom<>0);
122+ Filer.DefineProperty('MyRect',@ReadMyRect,@WriteMyRect,MyRectMustBeSaved);
123+end;
124+
125+procedure TMyComponent.ReadMyRect(Reader: TReader);
126+begin
127+ with Reader do begin
128+ ReadListBegin;
129+ FMyRect.Left:=ReadInteger;
130+ FMyRect.Top:=ReadInteger;
131+ FMyRect.Right:=ReadInteger;
132+ FMyRect.Bottom:=ReadInteger;
133+ ReadListEnd;
134+ end;
135+end;
136+
137+procedure TMyComponent.WriteMyRect(Writer: TWriter);
138+begin
139+ with Writer do begin
140+ WriteListBegin;
141+ WriteInteger(FMyRect.Left);
142+ WriteInteger(FMyRect.Top);
143+ WriteInteger(FMyRect.Right);
144+ WriteInteger(FMyRect.Bottom);
145+ WriteListEnd;
146+ end;
147+end;
148+```
149+
150+Dies wird MyRect als Eigenschaft 'MyRect' speichern.
151+
152+Falls Sie oft TRect streamen , dann wollen sie wahrscheinlich nicht jedes Mal den ganzen Code schreiben.
153+
154+Die Unit LResources enthält ein Beispiel, wie man eine Prozedur schreibt, um eine rect Eigenschaft zu definieren:
155+
156+```delphi
157+procedure DefineRectProperty(Filer: TFiler; const Name: string; ARect, DefaultRect: PRect);
158+```
159+
160+Auf diese Art kann der obige Code kurz gehalten werden :
161+
162+```delphi
163+procedure TMyComponent.DefineProperties(Filer: TFiler);
164+begin
165+ inherited DefineProperties(Filer);
166+ DefineRectProperty(Filer,'MyRect',@FMyRect,nil);
167+end;
168+```
169+
170+## Schreiben ihrer eigenen Komponente - Teil 2
171+
172+Jetzt kann das Beispiel erweitert werden und wir können beliebige Eigenschaften verwenden mit nur ein paar Zeilen Code:
173+
174+```delphi
175+type
176+ TMyComponent = class(TComponent)
177+ private
178+ FID: integer;
179+ FRect1: TRect;
180+ FRect2: TRect;
181+ protected
182+ procedure DefineProperties(Filer: TFiler); override;
183+ public
184+ property Rect1: TRect read FRect1 write FRect1;
185+ property Rect2: TRect read FRect2 write FRect2;
186+ published
187+ property ID: integer read FID write FID;
188+ end;
189+
190+procedure TMyComponent.DefineProperties(Filer: TFiler);
191+begin
192+ inherited DefineProperties(Filer);
193+ DefineRectProperty(Filer,'Rect1',@FRect1,nil);
194+ DefineRectProperty(Filer,'Rect2',@FRect2,nil);
195+end;
196+```
197+
198+Diese Komponente kann nun gespeichert, geladen oder von den [[RTTI controls/de|RTTI Bedienelementen]] verwendet werden. Sie müssen keinen weiteren Code schreiben.
199+
200+## Writing and Reading components from/to LFM
201+
202+Beispiele finden Sie in der unit **lresources** : function ReadComponentFromTextStream und writeComponentAsTextToStream
203+
204+## Writing and Reading components from/to XML
205+
206+Streaming components ist einfach: Siehe das Beispiel in lazarus/examples/xmlstreaming/.
207+
208+## Fazit
209+
210+<abbr title="Run Time Type Information">RTTI</abbr> 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.
211+
212+## Siehe auch
213+
214+- [[RTTI controls/de|RTTI controls]]
215+
216+---
217+*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).*
218+Category: Components/de
219+Category: Deutsch
220+Category: Tutorials/de

Back to history