English 中文(简体)
复制 delphi/freepascal 收集以高效网格
原标题:copy delphi/freepascal collection to grid efficiently

我试图找到最有效的方法, 从 Delphi/Lazarus FreePascal 收藏中更新网格( StringGrid 或 KGrid ) 。

我的一个收藏品如下:

{ TEntretien }
TEntretien = class(TCollectionItem)
private
  { private declarations }
  FPrenom: string;
  FSexe: string;
  FSigneDistinctif: string;
  FPays: string;
  FTotale: integer;
  FColumns: integer;
public
  { public declarations }
published
  { published declarations }
  property Prenom: string read FPrenom write FPrenom;
  property Sexe: string read FSexe write FSexe;
  property SigneDistinctif: string read FSigneDistinctif write FSigneDistinctif;
  property Pays: string read FPays write FPays;
property Totale: integer read FTotale write FTotale;
end;

{ TEntretiens }
TEntretiens = class(TCollection)
private
  { private declarations }
  function GetItem(AIndex: integer): TEntretien;
public
  { public declarations }
  constructor Create;
  function Add: TEntretien;
  property Items[AIndex: integer]: TEntretien read GetItem; default;
end;

我有以下代码片段,用来更新我的网格之一:

// Fill the grid with the results of the query
for intGridRow := 0 to intNumberOfRows - 1 do
begin
  for intGridCol := 0 to intNumberOfColumns - 1 do
  begin
    // Write the rest of the retrieved data into the grid proper   USE RTTI HERE??
    if intGridCol = 0 then
      kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] := 
         AEntretiens[intGridRow].Prenom
    else if intGridCol = 1 then
       kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] :=
         AEntretiens[intGridRow].Sexe
    else if intGridCol = 2 then
       kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] :=
         AEntretiens[intGridRow].SigneDistinctif
    else if intGridCol = 3 then
       kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] :=
         AEntretiens[intGridRow].Pays
    else if intGridCol = 4 then
       kgGridName.Cells[intGridCol + kgGridName.FixedCols, intGridRow + kgGridName.FixedRows] := IntToStr(AEntretiens[intGridRow].Totale)
    end;
end;

这对少量字段/财产的收藏来说是罚款,但我也有多达40个字段的收藏,所以我上面使用的方法太麻烦了。

是否有更有效的方法这样做?有人建议RTTI,但我不知道如何使用它。

非常感谢

达尼尔

最佳回答

这是戴尔菲增强的RTTI执行。 这是从戴尔菲- 2010 年生效的 。

它将查找所有可读的已出版属性(按申报的顺序),并填入数值。

如果您的属性为整数和字符串以上,请在语句中添加更多的内容。

uses
  System.Classes,System.RTTI,System.TypInfo, System.SysUtils;

procedure Test;
// Fill the grid with the results of the query
Var
  AnItem     : TEntretien;
  fixedCols  : integer;
  fixedRows  : integer;
  ARow,ACol  : integer;
  intGridRow : integer;
  context    : TRttiContext;
  rType      : TRttiType;
  prop       : TRttiProperty;
  value      : TValue;
  s          : String;
begin
  context := TRttiContext.Create;
  rType := context.GetType(TEntretien);
  fixedCols := kgGridName.FixedCols;
  fixedRows := kgGridName.FixedRows;
  for intGridRow := 0 to intNumberOfRows - 1 do
  begin
    AnItem := AEntretiens[intGridRow];
    ARow := intGridRow + fixedRows;
    ACol := fixedCols;
    for prop in rType.GetProperties do
    begin
      if prop.IsReadable then
      begin
        s :=   ;
        value := prop.GetValue(AnItem);
        case prop.PropertyType.TypeKind of
          tkInteger : s := IntToStr(value.AsInteger);
          tkString : s := value.AsString;
        end;
        kgGridName.Cells[ACol, ARow] := s;
        Inc(ACol);
      end;
    end;
  end;
end;

正如Ken在评论中所提到的,在Lazarus/FreePascal没有实施强化RTTI。

然后,所有平台的一个通用解决方案是增加一个收集项目基级,并有可能获得属性值。

Type
  TBaseItemClass = class(TCollectionItem)
    private
      function GetPropertyCount : integer; virtual; abstract;  
      function GetPropertyString( index : integer) : string; virtual; abstract;
    public
      property PropertyCount : integer read GetPropertyCount;
      property PropertyString[index : integer] : string read GetPropertyString;
  end;

那么你们的宣言和执行将看起来是这样的:

{ TEntretien }
TEntretien = class(TBaseItemClass)
private
  { private declarations }
  FPrenom: string;
  FSexe: string;
  FSigneDistinctif: string;
  FPays: string;
  FTotale: integer;
  FColumns: integer;
  function GetPropertyCount : integer; override;
  function GetPropertyString( index : integer) : string; override;
public
  { public declarations }
published
  { published declarations }
  property Prenom: string read FPrenom write FPrenom;
  property Sexe: string read FSexe write FSexe;
  property SigneDistinctif: string read FSigneDistinctif write FSigneDistinctif;
  property Pays: string read FPays write FPays;
  property Totale: integer read FTotale write FTotale;
end;

function TEntretien.GetPropertyCount : integer;
begin
  Result := 5;
end;

function TEntretien.GetPropertyString(index : integer) : string;
begin
  Result :=   ;
  case index of
    0 : Result := Prenom;
    1 : Result := Sexe;
    2 : Result := SigneDistinctif;
    3 : Result := Pays;
    4 : Result := IntToStr(Totale);
  end;
end;

procedure Test1;
// Fill the grid with the results of the query
Var
  AnItem    : TEntretien;
  intGridRow,intNumberOfRows : Integer;
  fixedCols : integer;
  fixedRows : integer;
  ARow      : integer;
  i         : integer;
begin
  fixedCols := kgGridName.FixedCols;
  fixedRows := kgGridName.FixedRows;
  for intGridRow := 0 to intNumberOfRows - 1 do
  begin
    AnItem := AEntretiens[intGridRow];
    ARow := intGridRow + FixedRows;
    for i := 0 to AnItem.PropertyCount - 1 do
    begin
      kgGridName.Cells[i + FixedCols, ARow] := AnItem.PropertyString[i];
    end;
  end;
end;

只是填充 GetPropertyCount 和 GetPropertyString 执行部分 在您的 TENDRETIEN 类。

这样做的方式可能似乎与你的例子一样效率低下,因为必须用手对所有财产价值进行编码。 但是,像我的例子一样,在方案规划中遵循两项基本原则:

  • Don t repeat yourself. If you have many grids to fill, the code would have to be repeated in many places. Now it s declared once and for all within the Collection item. Should you redesign the item, just update the two functions.
  • Keep the scope limited. The GUI part of your program should know as little as possible about the collection item class.
问题回答

暂无回答




相关问题
determining the character set to use

my delphi 2009 app has a basic translation system that uses GNUGetText. i had used some win API calls to prepare the fonts. i thought it was working correctly until recently when someone from Malta ...

Help with strange Delphi 5 IDE problems

Ok, I m going nuts here. For the last (almost) four years, I ve been putting up with some extremely bad behavior from my Delphi 5 IDE. Problems include: Seemingly random errors in coride50.bpl ...

How to write a Remote DataModule to run on a linux server?

i would like to know if there are any solution to do this. Does anyone? The big picture: I want to access data over the web, using my delphi thin clients. But i´would like to keep my server/service ...

How convert string to integer in Oxygene

In Delphi, there is a function StrToInt() that converts a string to an integer value; there is also IntToStr(), which does the reverse. These functions doesn t appear to be part of Oxygene, and I can ...

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...

热门标签