Delphi→ Компоненты в массиве TObjectList

Сен 16, 2010


Недавно, при написании одной из программ, столкнулся с проблемой большого количества элементов на форме. А именно 20 объектов TShape, 20 объектов TEdit и 100 объектов TMaskEdit.

Проблема заключается в том, что при операциях с этими элементами через программный код, его необходимо было бы тиражировать ровно столько раз, сколько этих элементов, а в каждой новой копии изменять только имя элемента (например, Edit1Edit2 и т.д.) Недостатки такого метода достаточно серьезны: большая вероятность допустить ошибку при изменении имени в каждом блоке; в случае каких-либо изменений кода, его потребуется менять во всех блоках; исходник разрастается до тысяч строк и становится менее понятен и т.д. Обратится к элементам, как к массиву, в виде Edit[i].Text в цикле не получится.

Что же делать? Мы будем использовать класс TObjectList из модуля Contnrs, который позволит нам добавить все элементы в массив, после чего к ним можно обращаться через индекс.

uses Windows, [...], Contnrs;

Как пользоваться? Для начала необходимо добавить в раздел uses модуль Contnrs, затем для каждого типа объекта (TShapeTEditTMaskEdit и т.д.) определить класс на основе TObjectList.

Пример для TEdit (размещается между uses и implementation):

type
  TEditList = class(TObjectList)
  {TEditList имя нового класса, на основе TObjectList}
private
  function GetItems(Index: Integer): TEdit; {Заменить TEdit на нужный тип: TShape, TMaskEdit и т.д.}
  procedure SetItems(Index: Integer; const Value: TEdit);  {Заменить TEdit на нужный тип: TShape, TMaskEdit и т.д.}
published
public
  property Items[Index: Integer]: TEdit read GetItems write SetItems; default; {Заменить TEdit на нужный тип: TShape, TMaskEdit и т.д.}
end;

Затем добавляем объявленные функции и процедуры после строки implementation. Эти функции отвечают за установление и получение значений через оператор квадратные скобки [].

{GetItems}
function TEditList.GetItems(Index: Integer): TEdit; {Заменить TEdit на нужный тип: TShape, TMaskEdit и т.д.}
begin
  Result := TEdit(inherited GetItem(Index)); {Заменить TEdit на нужный тип: TShape, TMaskEdit и т.д.}
end;
{SetItems}
procedure TEditList.SetItems(Index: Integer; const Value: TEdit); {Заменить TEdit на нужный тип: TShape, TMaskEdit и т.д.}
begin
  inherited SetItem(Index, Value);
end;

Теперь можно объявить переменную этого класса и использовать её как массив, предварительно заполнив его нужными элементами.

Объявляем переменную EditList:

var
EditList: TEditList;

Добавляем в массив визуальные элементы (код можно разместить в событии OnCreateформы):

EditList := TEditList.Create();
EditList.Add(Edit1.Text);
EditList.Add(Edit2.Text);
EditList.Add(Edit3.Text);
EditList.Add(Edit4.Text);
...

Пример обращения к элементу Edit1.Text:

EditList[0].Text := 'TEST';

Исходный текст полностью:

unit main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, ComCtrls, Contnrs;

type
  TfrmCallbase = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Edit6: TEdit;
    Edit7: TEdit;
    Edit8: TEdit;
    Edit9: TEdit;
    Edit10: TEdit;
    Edit11: TEdit;
    Edit12: TEdit;
    Edit13: TEdit;
    Edit14: TEdit;
    Edit15: TEdit;
    Edit16: TEdit;
    Edit17: TEdit;
    Edit18: TEdit;
    Edit19: TEdit;
    Edit20: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
  public
  end;

type
TEditList = class(TObjectList)
  private
    function GetItems(Index: Integer): TEdit;
    procedure SetItems(Index: Integer; const Value: TEdit);
  published
  public
    property Items[Index: Integer]: TEdit read GetItems write SetItems; default;
  end;

var
  frmCallbase: TfrmCallbase;
  EditList: TEditList;

implementation

{$R *.dfm}

procedure TfrmCallbase.FormCreate(Sender: TObject);
begin
  EditList := TEditList.Create();
  EditList.Add(Edit1);
  EditList.Add(Edit2);
  EditList.Add(Edit3);
  EditList.Add(Edit4);
  EditList.Add(Edit5);
  EditList.Add(Edit6);
  EditList.Add(Edit7);
  EditList.Add(Edit8);
  EditList.Add(Edit9);
  EditList.Add(Edit10);
  EditList.Add(Edit11);
  EditList.Add(Edit12);
  EditList.Add(Edit13);
  EditList.Add(Edit14);
  EditList.Add(Edit15);
  EditList.Add(Edit16);
  EditList.Add(Edit17);
  EditList.Add(Edit18);
  EditList.Add(Edit19);
  EditList.Add(Edit20);

  for i:=0 to EditList.Count - 1 do
  EditList[i].Text = 'default';
end;

procedure TfrmCallbase.FormDestroy(Sender: TObject);
begin
  EditList.Free;
end;

function TEditList.GetItems(Index: Integer): TEdit;
begin
  Result := TEdit(inherited GetItem(Index));
end;

procedure TEditList.SetItems(Index: Integer; const Value: TEdit);
begin
  inherited SetItem(Index, Value);
end;

end.

Таким образом, мне удалось уменьшить функцию в 1000 строк до 46 (20 блоков по 46 строк). 

Похожие статьи:

  1. Создаем компонент TCP на Winsock (Часть 2)
  2. Утечка памяти в IEnumVARIANT
  3. Многопоточность в Delphi
  4. Количество элементов в IEnumVARIANT
  5. Создаем компонент TCP на Winsock (Часть 1)

Добавить комментарий

Ваш адрес email не будет опубликован.