热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

delphi容器类3.TCollection

TCollection是TCollectionItenm对象一个容器。类关系TObject→TPersistent每一个TCollection都拥有一组TCollect

TCollection 是TCollectionItenm对象一个容器。


  类关系TObject→TPersistent


  每一个TCollection都拥有一组TCollectionItem对象。

  在其Items属性数组中,TCcllection保存集合项目一个下标。Count 属性包含了集合项目数量。
   使用Add和Clear方法可以向集合中加入项目和从集合中删除项目。

 

  从TCollection继承对象能够包含从TCollectionItem继承对象。
例如,一个TDBGridColumns对象包含TColumn对象,这两个类被TDBGrid对象用于表示网格。
下表列出了每一个TCollection对象子类与相应TCollectionltem对象子类以及使用控制组件。
其中,TQuryTableProducer和TWehDispetcher使用控件继承自TWinContril对象。


  TCollection子类 TCollectionItem子类 控件组件


  TCheckConstraints TCheckConstraint 使用Tfield对象控件

 

  TCOOKIECollection TCOOKIE HTTP响应对象

  TCoolBands TCoolBand TCoolBar

  TDBGridColumns TColumn TDBGrid

  TDependencies TDependency TService


  TDisplayDims TDisplayDim TDecisionGrid


  TFieldDefs TfieldDef TDatsSet 字串6

  THeaderSections THeaderSection THeaderControl 字串4

  TIndexDefs TIndexDef TTable

 

  THTMLTableColumns THTMLTableColumn TQueryTableProducer


  TListColumns TListColumn TListView


  TSuatusPanels TSuatuspanel TStatusBar

 

  TWebActionItems TwebActionitem TwebDispatcher

  使用TCollection和TCollectionitem子类控件,都有一个拥有一个集合5公开属性(
例如,TStatusBarPanels属性拥有一个TStatusPanels)。一个标准属性编辑器,从种属上说被认为是集合编辑器,
它被授引自Object Inspector,以编辑集合中项目。

 


  属性列表

  Count 返回集合中项目数量

  ItemClass 表示集合项目有种类


  Items 提供对集合中项目变址访问

 

  方法列表

  ~TCollection 删除集合及其内每一项目

  Add 创建一新对象实例并加 入到Items属性数组中


  Assign 将另一集合有内容复制到执行该方法对象中

  Bcginupdate 使屏幕更新暂停

  Clear 从集合中删除所有项目

  EndUpdate 使屏幕能够重新进行更新


  FindItemID 返回ID参数指定项目


  Insert 创建TCollectionItem对象并加入到Items属性数组中


  TCollection 创建并初始化一个集合 字串9

 

  属性

  TCollection::Count


  用于返回集合中项目数量。

 

  __property int Count = {read=getCount,nodefanlt};

 

  Count属性包含了Items属性数组中项目数量。因为Items属性数组下标从0开始,因此,Count属性数值总是比Items属性数组最后一个成员下标大1。 字串9

  TCollection::ItemClass

  表示集合项目类。

 


  __property int count = {read =GetXount,nodefauit};

 

  ItemClass返回属于集合项目类(继承自TColliectionItem对象)。
例如,在TCollection对象THeaderSections子类有一个实例中,IetmClass属性返回THeaderSection .


  TCollection::Items

  提供对集合中项目变址访问。

 

  __property TCollectionItem*irems{int Index}={read =GetItem,write=SetItem};


  使用Items属性可以访问集合中单个项目。Index参数数值对应于TCollectionItem对象Index属性。它表示项目 在集合中有位置。 字串2

  方法

  TCollection::~TCollection


  删除集合及其内每一个项目 。

 

  __fastcall virtual~TCollection(void);

 

  不要直接调用~TCollection 用delete会自动调用~TCollection

 

  ~TCollection调用Clear方法,释放在Items属性数组中每一个被子引用项目,然后删除集合本身。

  TCollection::Add

 


  创建一个新TCollectionItem对象实例,并将其加入到Items属性数组中。

 


  TCollectionItem* __fasteall Add(void);


  调用Add可以在集合中创建一个项目。新项目被放置在Items属性数组结尾处。Add返回新集合项目。

  TCollection::Assign 

  将另一个集合内容复制到执行该方法对象。

  virtual void __fastcall Assign (TPersistemt*Source);

 


  使用Assign,可以将一个TCollection对象实例内容复制至另一个TCollection对象。Assign方法删除目集合(即执行该方法对象)中所有项目,然后加入由Source参数指定集合Items属性数组中每一个项目复制。

 


  TCollection::BeginUpdate

  使屏幕更新暂停。

  void __fastcall BeginUpdate(void);

 


  BeginUpdate使屏幕更新暂停,直至调用了EndUpdate方法。使用BeginUpdate可以加速进行处理,并且当向一个集合中加入项目或从一个集合中删除项目时,可以避免闪烁。 字串3

  TCollection::EndUpdate

  从集合中删除所有项目。

  void __fastcall CIear(void);

 

  CIear清空Items属性数组并删除每一个TCollectionItem对象。

  TCollection::EndUpdate

  使屏幕能够重新进行更新。

  void __fastcall EndUpdate(void);

  使用EndUpdate,可以使以BeginUpdate方法关闭屏幕能够重新进行更新。

 

  TCollection::FindItemID

 

  返回ID参数指定项目。 字串1

  TCollectionItem* __fastcall FindItemID(int ID);

 


  FindItemID方法返回集合中项目,该项目ID属性被作为一个参数传递。如果没有ID参数指定项目,则FindItemID返回NULL.

字串8


  TCollection::Insert 字串6

  创建一个新TCollectionItem对象实例,并将其加入到Items属性数组中。 字串6

  TCollectionItem* __fastcall Insert(int Index);

字串7

  调用 Insert,可以在集合中一个指定位置处加入一个新项目。在Items属性数组中已经存在从指定位置开始项目将向上移动。Insert返回新集合项目。 字串4

  TColletion::TCollection 字串6

  创建并初始化一个集合。 字串3

  __fastcall TCollection (Sysem::TMetaCIass*ItemCIass);

字串5

  不要直接调用 TCollection。用new会返回新集合一个间接引用。

字串6


  TCollection方法取一个TCollectionItem子类名作为一个参数。该参数确定了由Add方法创建项目类。 字串2

 

====================================================================================

 

TCollection类

  前面我们提到了Delphi的IDE能够自动将字符串列表保存在DFM文件中,并能在运行时将设计期编辑的字符串列表加载进内存(也就是我们通常所说的类的可持续性)。TStrings这种特性比较适合于保存一个对象同多个字符串数据之间关联,比较类似于现实生活中一个人同多个Email账户地址之间的关系。但是,TStrings类型的属性有一个很大的局限那就是,它只能用于设计时保存简单的字符串列表,而不能保存复杂对象列表。而一个父对象同多个子对象之间的聚合关系可能更为常见,比如一列火车可能有好多节车厢构成,每节车厢都有车厢号,车厢类型(卧铺,还是硬座),车厢座位数,车厢服务员名称等属性构成。如果我们想在设计期实现对火车的车厢定制的功能,并能保存车厢的各个属性到窗体文件中,则车厢集合属性定义为TStrings类型的属性是行不通的。

  对于这个问题,Delphi提供了TCollection容器类属性这样一个解决方案。TCollection以及它的容器元素TCollectionItem的接口定义如下:

 TCollection = class(TPersistent)
 …
 protected
  procedure Added(var Item: TCollectionItem); virtual; deprecated;
  procedure Deleting(Item: TCollectionItem); virtual; deprecated;
  property NextID: Integer read FNextID;
  procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); virtual;
  { Design-time editor support }
  function GetAttrCount: Integer; dynamic;
  function GetAttr(Index: Integer): string; dynamic;
  function GetItemAttr(Index, ItemIndex: Integer): string; dynamic;
  procedure Changed;
  function GetItem(Index: Integer): TCollectionItem;
  procedure SetItem(Index: Integer; Value: TCollectionItem);
  procedure SetItemName(Item: TCollectionItem); virtual;
  procedure Update(Item: TCollectionItem); virtual;
  property PropName: string read GetPropName write FPropName;
  property UpdateCount: Integer read FUpdateCount;
 public
  constructor Create(ItemClass: TCollectionItemClass);
  destructor Destroy; override;
  function Owner: TPersistent;
  function Add: TCollectionItem;
  procedure Assign(Source: TPersistent); override;
  procedure BeginUpdate; virtual;
  procedure Clear;
  procedure Delete(Index: Integer);
  procedure EndUpdate; virtual;
  function FindItemID(ID: Integer): TCollectionItem;
  function GetNamePath: string; override;
  function Insert(Index: Integer): TCollectionItem;
  property Count: Integer read GetCount;
  property ItemClass: TCollectionItemClass read FItemClass;
  property Items[Index: Integer]: TCollectionItem read GetItem write SetItem;
 end;
 TCollectiOnItem= class(TPersistent)

 protected
  procedure Changed(AllItems: Boolean);
  function GetOwner: TPersistent; override;
  function GetDisplayName: string; virtual;
  procedure SetCollection(Value: TCollection); virtual;
  procedure SetIndex(Value: Integer); virtual;
  procedure SetDisplayName(const Value: string); virtual;
 public
  constructor Create(Collection: TCollection); virtual;
  destructor Destroy; override;
  function GetNamePath: string; override;
  property Collection: TCollection read FCollection write SetCollection;
  property ID: Integer read FID;
  property Index: Integer read GetIndex write SetIndex;
  property DisplayName: string read GetDisplayName write SetDisplayName;
 end;

  TCollection类是一个比较复杂特殊的容器类。但是初看上去,它就是一个TCollectionItem对象的容器类,同列表类TList类似,TCollection类也维护一个TCollectionItem对象索引数组,Count属性表示容器中包含的TCollectionItem的数目,同时也提供了Add和Delete方法来添加和删除TCollectionItem对象以及通过下标存取TCollectionItem的属性。看上去和容器类区别不大,但是在VCL内部用于保存和加载组件的TReader和TWriter类提供了两个特殊的方法WriteCollection和ReadCollection用于加载和保存TCollection类型的集合属性。IDE就是通过这两个方法实现对TCollection类型属性的可持续性。

  假设现在需要设计一个火车组件TTrain,TTrain组件有一个TCollection类型的属性Carriages表示多节车厢构成的集合属性,每个车厢则对应于集合属性的元素,从TCollectionItem类继承,有车厢号,车厢类型(卧铺,还是硬座),车厢座位数,车厢服务员名称等属性,下面是我设计的组件的接口:

type
 //车厢类型,硬座、卧铺
 TCarriageType = (ctHard, ctSleeper);
 //车厢类
 TCarriageCollectiOnItem= class(TCollectionItem)

 published
  //车厢号码
property CarriageNum: Integer read FCarriageNum write FCarriageNum;
//座位数
property SeatCount: Integer read FSeatCount write FSeatCount;
//车厢类型
property CarriageType: TCarriageType read FCarriageType write FCarriageType;
//服务员名称
  property ServerName: string read FServerName write FServerName;
 end;
 TTrain=class;
 //车厢容器属性类 
 TCarriageCollection = class(TCollection)
 private
  FTrain:TTrain;
  function GetItem(Index: Integer): TCarriageCollectionItem;
  procedure SetItem(Index: Integer; const Value: TCarriageCollectionItem);
 protected
  function GetOwner: TPersistent; override;
 public
  constructor Create(ATrain: TTrain);
  function Add: TCarriageCollectionItem;
property Items[Index: Integer]: TCarriageCollectionItem read GetItem
write SetItem; default;
 end;
 //火车类
 TTrain = class(TComponent)
 private
  FItems: TCarriageCollection;
  procedure SetItems(Value: TCarriageCollection);
 public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;
 published
  property Carriages: TCarriageCollection read FItems write SetItems;
 end;

  其中车厢类的定义非常简单,只是定义了四个属性。而车厢集合类重定义了静态的Add方法以及Items属性,其返回结果类型改为了TCarriageCollectionItem,下面是车厢集合类的实现代码:

function TCarriageCollection.Add: TCarriageCollectionItem;
begin
 Result:=TCarriageCollectionItem(inherited Add);
end;
  
constructor TCarriageCollection.Create(ATrain: TTrain);
begin
 inherited Create(TCarriageCollectionItem);
 FTrain:=ATrain;
end;
  
function TCarriageCollection.GetItem(
 Index: Integer): TCarriageCollectionItem;
begin
 Result := TCarriageCollectionItem(inherited GetItem(Index));
end;
  
function TCarriageCollection.GetOwner: TPersistent;
begin
 Result:=FTrain;
end;
  
procedure TCarriageCollection.SetItem(Index: Integer;
 const Value: TCarriageCollectionItem);
begin
 inherited SetItem(Index, Value);
end;

  其中Add,GetItem和SetItem都非常简单,就是调用基类的方法,然后将基类的方法的返回结果重新映射为TCollectionItem类型。而构造函数中将TTrain组件作为父组件传入,并重载GetOwner方法,返回TTrain组件,这样处理的原因是IDE会在保存集合属性时调用集合类的GetOwner确认属性的父控件是谁,这样才能把集合属性写到DFM文件中时,才能存放到正确的位置下面,建立正确的聚合关系。

  而火车组件的实现也非常简单,只要定义一个Published Carriages属性就可以了,方法实现代码如下:

constructor TTrain.Create(AOwner: TComponent);
begin
 inherited;
 FItems := TCarriageCollection.Create(Self);
end;
  
destructor TTrain.Destroy;
begin
 FItems.Free;
 inherited;
end;
  
procedure TTrain.SetItems(Value: TCarriageCollection);
begin
 FItems.Assign(Value);
end;

  下面将我们的组件注册到系统面板上之后,就可以在窗体上放上一个TTrain组件,然后然后选中Object Inspector,然后双击Carriages属性,会显示系统默认的集合属性编辑器,使用Add按钮向列表中添加两个车厢,修改一下属性,如下图所示意:

Delphi中的容器类

  从上面的属性编辑器我们,可以看到默认情况下,属性编辑器列表框是按项目索引加上一个横杠来显示车厢的名称,看起来不是很自然。要想修改显示字符串,需要重载TCarriageCollectionItem的GetDisplayName方法。修改后的GetDisplayName方法显示车厢加车厢号码:

function TCarriageCollectionItem.GetDisplayName: string;
begin
 Result:='车厢'+IntToStr(CarriageNum);
end;

  示意图:

Delphi中的容器类

  保存一下文件,使用View As Text右键菜单命令察看一下DFM文件,我们会看到我们设计的车厢类的属性确实都被写到了DFM文件中,并且Carriages属性的父亲就是Train1:

 object Train1: TTrain
  Carriages = <
   item
    CarriageNum = 1
    SeatCount = 100
    CarriageType = ctHard
    ServerName = '陈省'
   end
   item
    CarriageNum = 2
    SeatCount = 200
    CarriageType = ctHard
    ServerName = 'hubdog'
   end>
  Left = 16
  Top = 8
 End

  TOwnedCollection

  从Delphi4开始,VCL增加了一个TOwnedCollection类,它是TCollection类的子类,如果我们的TCarriageCollection类是从TOwnedCollection类继承的,这时我们就不再需要向上面重载GetOwner方法并返回父控件给IDE,以便TCarriageCollection属性能出现在Object Inspector中了。

  总结

  本章中我介绍了几乎所有VCL中重要的容器类,其中TList及其子类相当于通用的容器类,虽然不如C++和Java功能那么强大,但是用好了已经足以满足我们90%的开发需要,而TStrings及其子类,还有TCollection则是实现所见即所得设计的关键类,对于开发灵活强大的自定义组件来说是必不可少的。

 


推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 标题: ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • 本文介绍了Java的公式汇总及相关知识,包括定义变量的语法格式、类型转换公式、三元表达式、定义新的实例的格式、引用类型的方法以及数组静态初始化等内容。希望对读者有一定的参考价值。 ... [详细]
author-avatar
欧阳俊俊2502921727
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有