如何在delphi中实现对象序列化(100分)

  • 主题发起人 主题发起人 icelily7631
  • 开始时间 开始时间
I

icelily7631

Unregistered / Unconfirmed
GUEST, unregistred user!
对序列化的概念不是很清楚,更不知在delphi中如何实现,还望各位大虾不吝赐教
 
如果是自定义结构的数据,就用TStream及其相关的一些类;
如果是自定义的类,应该从RTTI入手,将对象存储起来。
第一种情况并不复杂。看看帮助估计就没问题了。
第二种情况需要一些比较深的知识,建议找一本书《DELPHI 高级开发指南》(1997,电子工业出版社,Macro Cantu)
里面有类的流化知识。如果找不到看看TResourceStream等相关的主题。
 
能不能具体一点,我看了一下tstream类好象是可把一个tcomponent及属性写入流中,那具体来说
如对一个tchart而言,是能把他其上所有的series数及每条series的点数都完全写入流中再
恢复吗能不能给个简单示例,如在一个form中点一下按钮就可把原有的一个chart原封不动的
复制到一个新位置,急急急!!!!
 
to wk_knife:
能尽快回答我的问题?我试了一下午好象都只能把chart写入再恢复,可对于动态加入的
series的点信息却无法用tstream方式保存是不是根本无法实现把tchart及其中所有的series
信息同时写入一个tstream再恢复的功能。如可以的话应怎么做能不能发个例子我的地址是
icelily7631@sina.com,不胜感激!!
 
我给你一个简单的例子吧,从书上摘来的。
DELPHIPT.PAS
unit DelphiPt;
interface
uses
Classes, Graphics;
type
TDDHPoint = class (TCollectionItem)
private
fX, fY: Integer;
public
Text: string;
procedure WriteText (Writer: TWriter);
procedure ReadText (Reader: TReader);
procedure DefineProperties (Filer: TFiler);
override;
procedure Paint (Canvas: TCanvas);
procedure Assign (Pt: TPersistent);
override;
published
property X: Integer read fX write fX;
property Y: Integer read fY write fY;
end;

TWrapper = class (TComponent)
private
FColl: TCollection;
published
property MyColl: TCollection read FColl write FColl;
public
constructor Create (Owner: TComponent);
override;
destructor Destroy;
override;
end;

implementation
// TWrapper constructor and destructor
constructor TWrapper.Create (Owner: TComponent);
begin
inherited Create (Owner);
FColl := TCollection.Create (TDDHPoint);
end;

destructor TWrapper.Destroy;
begin
FColl.Clear;
FColl.Free;
inherited Destroy;
end;

// class TDDHPoint methods
procedure TDDHPoint.WriteText (Writer: TWriter);
begin
Writer.WriteString (Text);
end;

procedure TDDHPoint.ReadText (Reader: TReader);
begin
Text := Reader.ReadString;
end;

procedure TDDHPoint.DefineProperties (Filer: TFiler);
begin
Filer.DefineProperty (
'Text', ReadText, WriteText, (Text <> ''));
end;

procedure TDDHPoint.Paint (Canvas: TCanvas);
begin
Canvas.Ellipse (fX - 3, fY - 3, fX + 3, fY + 3);
Canvas.TextOut (fX + 5, fY + 5, Text);
end;

procedure TDDHPoint.Assign (Pt: TPersistent);
begin
if Pt is TDDHPoint then
begin
fx := TDDHPoint (Pt).fX;
fY := TDDHPoint (Pt).fY;
Text := TDDHPoint (Pt).Text;
end
else
// raise an exception
inherited Assign (pt);
end;

//initialization
//RegisterClass (TWrapper);
end.

PERSFORM.DFM
object Form1: TForm1
Left = 295
Top = 161
Width = 462
Height = 300
Caption = 'Persist'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OnCreate = FormCreate
OnDestroy = FormDestroy
OnMouseDown = FormMouseDown
OnPaint = FormPaint
PixelsPerInch = 96
TextHeight = 13
object Panel1: TPanel
Left = 0
Top = 0
Width = 454
Height = 39
Align = alTop
ParentShowHint = False
ShowHint = False
TabOrder = 0
object Label1: TLabel
Left = 8
Top = 12
Width = 106
Height = 13
Caption = 'Enter name then
click:'
end
object SpeedButtonLoad: TSpeedButton
Left = 256
Top = 8
Width = 49
Height = 25
Caption = 'Load...'
NumGlyphs = 2
OnClick = SpeedButtonLoadClick
end
object SpeedButtonSave: TSpeedButton
Left = 304
Top = 8
Width = 49
Height = 25
Caption = 'Save...'
NumGlyphs = 2
OnClick = SpeedButtonSaveClick
end
object Edit1: TEdit
Left = 120
Top = 8
Width = 121
Height = 21
TabOrder = 0
Text = 'Point 1'
end
end
object OpenDialog1: TOpenDialog
DefaultExt = 'prs'
Filter = 'Persistent File (*.prs)|*.prs|Any file (*.*)|*.*'
Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist]
Left = 32
Top = 64
end
object SaveDialog1: TSaveDialog
DefaultExt = 'prs'
Filter = 'Persistent File (*.prs)|*.prs|Any file (*.*)|*.*'
Options = [ofHideReadOnly, ofPathMustExist, ofCreatePrompt]
Left = 112
Top = 65
end
end
PERSFORM.PAS
unit PersForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Buttons, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Label1: TLabel;
Edit1: TEdit;
SpeedButtonLoad: TSpeedButton;
SpeedButtonSave: TSpeedButton;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
procedure FormCreate(Sender: TObject);
procedure SpeedButtonSaveClick(Sender: TObject);
procedure SpeedButtonLoadClick(Sender: TObject);
procedure FormMouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState;
X, Y: Integer);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
PtList: TCollection;
end;

var
Form1: TForm1;
implementation
{$R *.DFM}
uses
DelphiPt;
procedure TForm1.FormCreate(Sender: TObject);
begin
PtList := TCollection.Create (TDDHPoint);
end;

procedure TForm1.SpeedButtonSaveClick(Sender: TObject);
var
Str1: TFileStream;
Wrap: TWrapper;
begin
if SaveDialog1.Execute then
begin
Str1 := TFileStream.Create (SaveDialog1.FileName,
fmOpenWrite or fmCreate);
try
Wrap := TWrapper.Create (self);
try
Wrap.MyColl.Assign (ptList);
Str1.WriteComponent (Wrap);
finally
Wrap.Free;
end;
finally
Str1.Free;
end;
end;
end;

procedure TForm1.SpeedButtonLoadClick(Sender: TObject);
var
Str1: TFileStream;
Wrap: TWrapper;
begin
if OpenDialog1.Execute then
begin
Str1 := TFileStream.Create (
OpenDialog1.Filename, fmOpenRead);
try
Wrap := TWrapper.Create (self);
try
Wrap := Str1.ReadComponent (Wrap) as TWrapper;
ptList.Assign (Wrap.MyColl);
finally
Wrap.Free;
end;
finally
Str1.Free;
Invalidate;
Edit1.Text := 'Point ' + IntToStr (PtList.Count + 1);
end;
end;
end;

procedure TForm1.FormMouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState;
X, Y: Integer);
var
Pt: TDDHPoint;
begin
Pt := PtList.Add as TDDHPoint;
Pt.X := X;
Pt.Y := Y;
Pt.Text := Edit1.Text;
Edit1.Text := 'Point ' + IntToStr (PtList.Count + 1);
Invalidate;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
// empty and destroy the list
PtList.Clear;
PtList.Free;
end;

procedure TForm1.FormPaint(Sender: TObject);
var
I: Integer;
begin
for I := 0 to PtList.Count - 1do
TDDHPoint (PtList.Items ).Paint (Canvas);
end;

end.

PERSIST.DPR
program Persist;
uses
Forms,
PersForm in 'PersForm.pas' {Form1},
DelphiPt in 'DelphiPt.pas';
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

--------------------------------------------------------------------------------



 
对于你的情况,如果是自己做一个Chart是可以实现的
如果用DELPHI自带的估计是无法通过这种方式来实现。
你可以这样做
TPointArray=Array of TPoint;
//为绘制曲线定义的点集,你可以将点也按上面的例子序列化,也可以定义存储结构通过流式存储
TChart=class;
TSerial=class;
TSerials=class(TCollection) //曲线集
private
FChart:TChart;
//所指向的GraphicControl
function GetItem(index: Integer): Tserial;
procedure SetItem(index: Integer;
const Value: Tserial);
protected
procedure Update(Item:TCollectionItem);override;
public
constructor Create(AChart:TChart);
function Add:TSerial;
//添加曲线
function Insert(Index: Integer):Tserial;
//插入曲线
procedure Clear;
//清空
procedure Delete(Index: Integer);
//删除曲线
property Item[index:Integer]:Tserial read GetItem write SetItem;default;
//得到某一条
end;

TCurve=class(TCollectionItem)
private
FPointArray: TPointArray;
//点集
procedure SetPointArray(const Value: TPointArray);
public
property PointArray:TPointArray read FPointArray write SetPointArray;
//对应的点集
published
procedure Paint(ACanvas:TCanvas);
//绘制点集
constructor Create(Collection: TCollection);override;
destructor Destroy;
override;
end;

TChart=class(TGraphicControl)
private
FSerials:TSerials;//曲线集,你可以为它做属性编辑器,如同DBGrid的Columns属性。
public
constructor Create(Owner:TComponent);override;
destructor Destroy;override;
procedure Paint;override;
property Canvas;
published
property Serials:TSerials read FSerials write FSerials;
end;

大体上就是如此的一个类结构,具体的就很抱歉了。如果我有时间,倒也愿意再做一做。
建议找点关于TCollection的文章读读。
 
多人接受答案了。
 
后退
顶部