依旧的博客

技术学习

C++博客 首页 新随笔 联系 聚合 管理
  17 Posts :: 1 Stories :: 2 Comments :: 0 Trackbacks
 

视图用来表现数据,也是用户接口。当数据更新时,视图应该随之改变,在交互过程中,视图需要响应用户,这些情况下都会引起视图的绘制。 cxGrid可以用多种视图表现关系型数据,最常用的是表格视图,我们以表格视图作为默认的对象,分析cxGrid用以实现视图绘制的基本结构。

 

表格视图按行,列布局,行优先顺序绘制,绘制的基本元素是行和单元(cell)。由于数据内容的动态性,行是动态生成的。表格视图提供了各种可定制性,包括可选的分组行风格和若干自定义风格,这些复杂特性背后有很好的设计。

 

视图绘制相关的几组类:

 

ViewInfo类族:

描述视图元素的绘制信息,视图元素要绘制成什么样子,完全由其ViewInfo确定。祖先类是TcxCustomGridCellViewInfo,数据行,数据单元,分组行等视图元素以及视图本身都有相应的派生类。

 

Painter类族:

按照ViewInfo,在画布上绘制视图元素。祖先类是TcxCustomGridCellPainter TcxCustomGridCellPainter = class

 private

    FCanvas: TcxCanvas;

FViewInfo: TcxCustomGridCellViewInfo;

 

View类族:

整个视图的描述,包括了各种设置信息。祖先是TcxCustomGridView

ViewViewInfo的不同在ViewInfo描述绘制信息,而View描述设置信息,ViewInfo是动态构造的,当Grid创建时,如果有一个分组多条记录,那么每条记录会生成一个ViewInfo实例,如果收起分组,这些实例将被销毁,展开分组,会再次生成每条记录的ViewInfo实例,而一个表格视图始终只有一个实例。

 

LookAndFeelPainter类族:

用于进行有关分组行风格的绘制。祖先是TcxCustomLookAndFeelPainter

绘制视图元素时,涉及到分组行风格(GroupRowStyle)的绘制任务,都被委托给LookAndFeelPainter类的实例,由此实现多态的风格。

 

StyleStyles类族:

Style类的祖先是TcxCustomStyleStyles类的祖先是TcxCustomStylesTcxCustomStyle类表示一种自定义风格,TcxCustomStyles类表示一组风格。TcxCustomStyles内部用一个map保存这些风格,给出键,可通过Values属性取出指定的风格。

TcxCustomStyles = class(TcxInterfacedPersistent, IcxStyleChangeListener)

public

property Values[Index: Integer]: TcxCustomStyle read GetValue write SetValue;

键的取值范围如下:

 vsCustomTableFirst = vsCustomLast + 1;

 vsContent = vsCustomTableFirst;

 vsContentEven = vsCustomTableFirst + 1;

 vsContentOdd = vsCustomTableFirst + 2;

 vsFilterBox = vsCustomTableFirst + 3;

 vsInactive = vsCustomTableFirst + 4;

 vsIncSearch = vsCustomTableFirst + 5;

 vsSelection = vsCustomTableFirst + 6;

// vsCustomTableLast = vsSelection;

 vsHotTrack = vsCustomTableFirst + 7;

 vsCustomTableLast = vsHotTrack;

 

考查以上几组类的关系:

 

PainterViewInfo

 

Painter类和ViewInfo类具有对应关系,在视图元素绘制时创建出Painter类的实例,其中有多态机制的作用,下面具体了解一下这个创建过程。

 

TcxCustomGridCellPainter派生的一组类中,只有它自己有构造函数:

constructor TcxCustomGridCellPainter.Create(ACanvas: TcxCanvas;

 AViewInfo: TcxCustomGridCellViewInfo);

begin

 inherited Create;

 FCanvas := ACanvas;

 FViewInfo := AViewInfo;

end;

那么当需要调用其派生类方法时,是如何构造出派生类实例的?Painter类实例都是在ViewInfo类的方法中创建出来的,代码如下:

GetPainterClass.Create()

 

TcxGridDataRowViewInfo = class(TcxCustomGridRowViewInfo)

protected:

function GetPainterClass: TcxCustomGridCellPainterClass; override;

 

 

function TcxGridDataRowViewInfo.GetPainterClass: TcxCustomGridCellPainterClass;

begin

 Result := TcxGridDataRowPainter;

end;

 

这样,创建哪个Painter类的实例决定于ViewInfo类的实例,通过某个ViewInfo实例调用GetPainterClass.Create(),就返回对应Painter类的实例。

 

ViewInfo类进行绘制时,会调用Painter类的绘制方法;Painter类进行绘制时,也会调用ViewInfo类的绘制方法,比如:

procedure TcxCustomGridRecordsPainter.Paint;

var

 I: Integer;

begin

 with FViewInfo do

    for I := 0 to Count - 1 do

      with Items[I] do

        if Calculated then Paint;

end;

跟踪绘制过程可以看到,正是在两种调用的交替中绘出了视图的每个元素,最终在显示设备上的绘制是由Painter类实现的,而ViewInfo的绘制方法会起到调度的作用,比如把数据行的绘制分解成各数据单元的绘制。

我们已经了解到,前一种调用是通过构造局部实例,那么后一种呢?

TcxCustomGridCellPainter中定义了FViewInfo私有成员,并将其定义为保护属性

 TcxCustomGridCellPainter = class

 private

    FCanvas: TcxCanvas;

FViewInfo: TcxCustomGridCellViewInfo;

 protected

property ViewInfo: TcxCustomGridCellViewInfo read FViewInfo;

其派生类继承了该属性,并将其重新定义

 TcxGridDataRowPainter = class(TcxCustomGridRowPainter)

 private

    function GetViewInfo: TcxGridDataRowViewInfo;

 protected

    property ViewInfo: TcxGridDataRowViewInfo read GetViewInfo;

 

function TcxGridDataRowPainter.GetViewInfo: TcxGridDataRowViewInfo;

begin

 Result := TcxGridDataRowViewInfo(inherited ViewInfo);

end;

 

ViewStyles

 

视图风格是视图的属性:

 TcxCustomGridView = class(TcxControlChildComponent, IcxStoredObject, IcxStoredParent,

    IcxGridViewLayoutEditorSupport, IcxGridViewDesignerMenu)

 private

FStyles: TcxCustomGridStyles;

 Protected:

property Styles: TcxCustomGridStyles read FStyles write SetStyles;

 

procedure TcxCustomGridView.SetStyles(Value: TcxCustomGridStyles);

begin

 FStyles.Assign(Value);

end;

 

特定的视图使用特定的视图风格,以表视图为例,可以看到两者是如何对应的。

TcxGridTableView = class(TcxCustomGridTableView)

Published:

property Styles: TcxGridTableViewStyles read GetStyles write SetStyles;

 

function TcxGridTableView.GetStyles: TcxGridTableViewStyles;

begin

 Result := TcxGridTableViewStyles(inherited Styles);

end;

 

procedure TcxGridTableView.SetStyles(Value: TcxGridTableViewStyles);

begin

 inherited Styles := Value;

end;

 

ViewLookAndFeelPainter

 

ViewInfoGridStylesGridView类都有LookAndFeelPainter属性,因为分组行风格设置是作用于整个视图的,所以该属性真正定义是在GridView中,GridStylesViewInfo只是返回一个引用,提供该属性是为了方便,比如ViewInfo进行绘制时,要用到风格的设置。

function TcxCustomGridView.GetLookAndFeelPainter: TcxCustomLookAndFeelPainterClass;

begin

 if Control = nil then

    Result := TcxStandardLookAndFeelPainter

 else

    Result := TcxCustomGrid(Control).LookAndFeelPainter;

end;

 

function TcxCustomGridStyles.GetLookAndFeelPainter: TcxCustomLookAndFeelPainterClass;

begin

 Result := GridView.LookAndFeelPainter;

end;

 

/* TcxGridViewHandler是视图ViewInfo的祖先类。*/

function TcxGridViewHandler.GetLookAndFeelPainter: TcxCustomLookAndFeelPainterClass;

begin

 Result := FGridView.LookAndFeelPainter;

end;

 

/* TcxCustomGridViewCellViewInfo是视图元素ViewInfo的祖先类,FGridViewInfoGridViewInfo属性的成员变量。*/

function TcxCustomGridViewCellViewInfo.GetLookAndFeelPainter: TcxCustomLookAndFeelPainterClass;

begin

 Result := FGridViewInfo.LookAndFeelPainter;

end;

posted on 2007-05-15 18:05 依旧的博客 阅读(1302) 评论(0)  编辑 收藏 引用 所属分类: 编程

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理