Delphi→ Компоненты в массиве TObjectList
Сен 16, 2010
Недавно, при написании одной из программ, столкнулся с проблемой большого количества элементов на форме. А именно 20 объектов TShape, 20 объектов TEdit и 100 объектов TMaskEdit.
Проблема заключается в том, что при операциях с этими элементами через программный код, его необходимо было бы тиражировать ровно столько раз, сколько этих элементов, а в каждой новой копии изменять только имя элемента (например, Edit1, Edit2 и т.д.) Недостатки такого метода достаточно серьезны: большая вероятность допустить ошибку при изменении имени в каждом блоке; в случае каких-либо изменений кода, его потребуется менять во всех блоках; исходник разрастается до тысяч строк и становится менее понятен и т.д. Обратится к элементам, как к массиву, в виде Edit[i].Text в цикле не получится.
Что же делать? Мы будем использовать класс TObjectList из модуля Contnrs, который позволит нам добавить все элементы в массив, после чего к ним можно обращаться через индекс.
uses Windows, [...], Contnrs;
Как пользоваться? Для начала необходимо добавить в раздел uses модуль Contnrs, затем для каждого типа объекта (TShape, TEdit, TMaskEdit и т.д.) определить класс на основе 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 строк).
Похожие статьи: