Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Добавить материал
 

TObjectList
Sunr1se
Репутация: 6
Всего: 13

Профиль
FAQ: 3110 Быстрая цитата Цитата
Теги:
TObjectList

TObjectList предназначен для динамического хранения потомков класса TObject. У него есть множество преимуществ: контроль за памятью, возможность сортировки, отслеживания пустых элементов. Он имеет очень хорошие возможности по работе с объектами. Все это делает TObjectList наиболее удобным средством для хранения объектов и управления ими.

Рассмотрим методы этого класса.

Методы класса TObjectList:
Create
Код

constructor Create(AOwnsObjects: Boolean);

Создает новый ObjectList. Параметр AOwnsObjects определяет, как будут уничтожаться объекты в случае их удаления из списка. Если AOwnsObjects установлен в true, это будет происходить автоматически, если false – надо будет делать все самостоятельно. По 
умолчанию он равен true.

Add
Код

function Add(AObject: TObject): Integer;

Добавляет новый объект в конец списка, увеличивает свойство Count на единицу и, если необходимо, выделяет память, увеличивая значение Capacity (мы рассмотрим позже это свойство).

Extract
Код

function Extract(Item: TObject): TObject;

Удаляет объект из списка, не уничтожая его (даже если OwnsObjects равен true!). Item – это имя удаляемого объекта. Индекс элементов, которые стояли после удаленного, автоматически уменьшается на единицу, а также уменьшается свойство Count. Функция возвращает только что удаленный из списка объект.

Insert
Код

procedure Insert(Index: Integer; AObject: TObject);

Вставляет новый объект на указанную позицию, сдвигая стоящий на этом месте элемент, а также все следующие за ним элементы. Index – позиция, на которую вставляется объект, указанный в AObject. При необходимости для нового элемента выделяется память.

First
Код

function First: TObject;

Возвращает первый элемент списка.

Last
Код

function Last: TObject;

Возвращает последний элемент списка.

FindInstanceOf
Код

function FindInstanceOf(AClass: TClass; AExact: Boolean = True; AStartAt: Integer = 0): Integer;

Возвращает индекс первого найденного объекта, который относится к классу, указанному в AClass. Поиск начинается с индекса, указанного в AStartAt. Если AExact равен false, то будет производиться поиск не только объектов класса AClass, но и его потомков.

IndexOf
Код

function IndexOf(AObject: TObject): Integer;

Возвращает индекс объекта AObject в списке.


Методы класса TList:

Remove
Код

function Remove(AObject: TObject): Integer;

Единственное отличие от Extract состоит в том, что удаленный элемент уничтожается, если OwnsObjects равен true. Возвращает индекс элемента до того, как он был удален.

Delete
Код

procedure Delete(Index: Integer);

Отличается от Extract тем, что в качестве параметра передается не имя, а индекс. Если OwnsObjects равен true, то сразу же вызывается метод Free. Чтобы вручную освободить память, которая использовалась для хранения объекта, достаточно уменьшить параметр Capacity. Индексы элементов и Count изменяются так же, как и у Extract.

Assign
Код

procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil);

Копирует элементы из одного списка в другой. Если ListB=nil, то элементы перемещаются из ListA в данный список, при этом используется оператор, указанный в AOperator.
Если ListB указан, то сначала все элементы данного списка копируются в ListA, а затем объекты из ListB перемещаются в данный список, при этом используется оператор, указанный в AOperator.
Теперь немного об этих операторах:
laAnd – удаляет из списка-получателя все элементы, которых нет в исходном списке.
laCopy – очищает список-получатель и полностью копирует в него исходный список (по умолчанию выбран этот вариант).
laDestUnique – удаляет из списка-получателя все элементы, которые присутствуют в исходном списке.
laOr – добавляет из исходного списка все элементы, которых нет в списке-получателе.
laSrcUnique – копирует из исходного списка все элементы, которых нет в списке-получателе, предварительно очистив список-получатель.
laXor – удаляет из списка-получателя те элементы, которые есть в исходном списке, затем добавляет туда из исходного списка элементы, которых изначально не было в списке-получателе.

Pack
Код

procedure Pack;

Удаляет из списка все элементы, равные nil, при этом Count присваивается значение, равное количеству используемых элементов (то есть не равных nil). Память, занимаемая ими, не освобождается. Чтобы очистить ее, надо произвести такое действие:
Код

ObjectList.Capacity := ObjectList.Count;


Expand
Код

function Expand: TList;

Увеличивает значение параметра Capacity (т.е. увеличивает вместимость). Работает только в том случае, если количество элементов в списке равно вместимости листа. Если значение Capacity больше, чем 8, Expand увеличивает вместимость списка до 16. Если значение Capacity больше 4, но меньше 9, Capacity увеличивается до 8. Если Capacity меньше 4, вместимость увеличивается до 4.
Функция возвращает сам ObjectList.

Clear
Код

procedure Clear;

Этот метод удаляет все элементы из списка, освобождает память, используемую для хранения объектов, а также присваивает свойству Capacity значение 0.

Exchange
Код

procedure Exchange(Index1, Index2: Integer);

Меняет местами два элемента списка.

Move
Код

procedure Move(CurIndex, NewIndex: Integer);

Перемещает элемент списка на другую позицию. CurIndex – текущий номер объекта, NewIndex – его новый номер.

Sort
Код

procedure Sort(Compare: TListSortCompare);

Метод сортирует элементы списка. В функции TListSortCompare должно быть указано, как следует располагать объекты в списке:
Код

TListSortCompare = function (Item1, Item2: Pointer): Integer;

Пример:
При нажатии на Button1 кнопки, которые перечислены  списке, будут расположены в алфавитном порядке (сравнение будет идти по параметру Caption):
Код

function CompareObjectName(Btn1, Btn2: TButton): integer;
begin
Result := CompareText(Btn1.Caption, Btn2.Caption);  //функция CompareText – стандартная, сравнивает две строки. Если первая строка больше, возвращает значение больше 0, если равны – возвращает 0, если вторая больше, то возвращает отрицательное число
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ObjList.Sort(@CompareObjectName);
end;



А теперь немного о свойствах TObjectList:
OwnsObjects
Код

property OwnsObjects: Boolean;

Позволяет TObjectList самостоятельно контролировать память, занимаемую объектами. Если его значение равно true, то:
  • Вызов методов Delete или Remove уничтожает объект, который был удален из списка
  • Процедура Clear не только удаляет объекты из списка, но и уничтожает их
  • Вызов деструктора уничтожает все элементы списка, а не только сам ObjectList
  • При добавлении нового объекта на определенную позицию уничтожается находившийся там ранее объект

Однако метод Extract будет в любом случае удалять объект из списка без его уничтожения.
Capacity
Код

property Capacity: Integer;

Определяет размер массива, в котором хранятся объекты. Если при добавлении нового элемента окажется, что список заполнен, то Capacity будет увеличено.
Count
Код

property Count: Integer;

Показывает, сколько элементов списка используется в данный момент. Если увеличить значение Count, то в список будут добавлены пустые указатели (nil). При его уменьшении будет удалено необходимое число записей.
Items
Код

property Items[Index: Integer]: TObject;  default;

С помощью Items можно получить доступ к объектам, хранящимся в списке.
Items является свойством по умолчанию, а значит следующие две строки равносильны:
Код

ObjectList.Items[1] := Button1;
ObjectList[1] := Button1;






Пора перейти от теории к практике. Вот несколько примеров, которые демонстрируют область применения TObjectList.
Пример 1. Работа с динамически созданными объектами (а именно с TEdit).
Нужно создать свой собственный класс, который будет потомком TObjectList. Для этого требуется перекрыть методы SetItems и GetItems. В интерфейсной части модуля, после слова type, пропишите такой код:
Код

EditList = class(TObjectList)
  public
    property Items[Index: Integer]: TEdit read GetItems write SetItems; default;  //чтение элементов списка будет происходить через метод GetItems, а запись - через SetItems
  end;

и нажмите Ctrl+Shift+C. В конце модуля сгенерируется:
Код


function TEditList.GetItems(Index: Integer): TEdit;
begin

end;

procedure TEditList.SetItems(Index: Integer; const Value: TEdit);
begin

end;


В GetItems вставьте строку
Код

Result := TEdit(inherited GetItem(Index));

В SetItems:
Код

inherited SetItem(Index, Value);

Теперь у нас есть класс, предназначенный для хранения TEdit’ов.


Приступим к работе с этим классом.

Код

var EditList: TObjectList;  //глобальная переменная

procedure TForm1.Button1Click(Sender: TObject);
var Edit: TEdit;
    i: integer;
begin
EditList := TObjectList.Create(true);
for i := 1 to 20 do
begin
  Edit := TEdit.Create(nil);
  Edit.Parent := Form1;
  Edit.Top := 40 + 25*i;
  Edit.Left := 120;
  Edit.Name := 'MyEdit'+IntToStr(i);    
  Edit.Text := '';
  EditList.Add(Edit);
end;
end;


Как вариант:

Код

procedure TForm1.Button1Click(Sender: TObject);
var Edit: TEdit;
    i: integer;
begin
EditList := TObjectList.Create(true);
for i := 1 to 3 do
begin
  Edit := TEdit.Create(nil);
  Edit.Parent := Form1;
  Edit.Top := 40 + 25*i;
  Edit.Left := 120;
  case i of
    1: Edit.Name := 'Surname';
    2: Edit.Name := 'Name';
    3: Edit.Name := 'Adress';
  end;
  Edit.Text := '';
  EditList.Add(Edit);
end;
end;



Теперь можно работать с Edit’ами так же, как с элементами массива:
Код

EditList[2].Text := '111';


При использовании второго способа индекс объекта знать не обязательно, нужно только его имя. Для удобства напишем функцию, которая находит Edit по его имени:

Код

function FindEdit(Name: string; List: TEditList): integer;
var i: integer;
begin
for i := 0 to List.Count-1 do
  if List[i].Name = Name then
    Result := i;
end;



Пример 2. Выравнивание компонентов.
Представим такую ситуацию: получилось, что динамически созданные компоненты на форме расположены как попало, и их надо выровнять. С помощью TObjectList очень легко решить эту задачу.
Этот код выравнивает на форме TEdit’ы (использован класс TEditList из предыдущего примера):
Код

function CompareObjectName(Obj1, Obj2: TEdit): integer;
begin
Result := CompareText(Obj1.Name, Obj2.Name);
end;

procedure TForm1.Button11Click(Sender: TObject);
var i: integer;
begin
EditList := TEditList.Create(true);
EditList.Add(Edit1);
EditList.Add(Edit2);
EditList.Add(Edit3);
EditList.Add(Edit4);
EditList.Add(Edit5);
EditList.Sort(@CompareObjectName);
for i := 0 to EditList.Count-1 do
  begin
  EditList[i].Left := 120;
  EditList[i].Top := 60+i*30;
  end;
end;



Пример 3.Работа с данными.
В этом примере я рассмотрю создание некого подобия адресной книги.
Для начала создадим класс, который нужен для хранения данных об отдельном человеке:

Код

  TInfo = class
    Surname: string;
    Name: string;
    Adress: string;
    Age: integer;
    Phone: string;
    Email: string;
  end;



Осталось создать класс, который будет потомком TObjectList и будет предназначен для хранения данных типа TInfo:

Код

  TAdressBook = class(TObjectList)
  public
    property Items[Index: Integer]: TInfo read GetItems write SetItems; default;
  end;


Нажмите Ctrl+Shift+C. Появятся два метода: GetItems и SetItems. Вот их код:

Код

function TAdressBook.GetItems(Index: Integer): TInfo;
begin
Result := TInfo(inherited GetItem(Index));
end;

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


Программа готова!

© Sunr1se


To moderators: пожалуйста, закрепите тему. 


Комментарии посетителей:


Дата 27.5.2006, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата
Snowy ****   Репутация: 192  Всего: 483 
Основное назначение TObjectList - работа с неопределенным количеством объектов.
В принципе для этого подходит и TList, но TObjectList специально предназначен именно для объектов.
Замечание:
Не рассмотрена работа с набором разнородных объектов, и разнородных объектов - наследников общего предка.
Например TWinControl.
Например, необязательно затачивать под TEdit. Достаточно под TWinControl.
После этого можно добавлять в список любые контролы и единообразно управлять ими.

Цитата(Sunr1se @  27.5.2006,  15:58 Найти цитируемый пост)
  EditList[i].Top := 60+i*30;
И чтобы вот так не делать, стоит воспользоваться свойством Height контрола + фиксированный интервал.

Цитата(Sunr1se @  27.5.2006,  15:58 Найти цитируемый пост)
Для этого требуется перекрыть методы SetItems и GetItems. В интерфейсной части модуля
Это минимум. Для полноценной работы также потребуется пронаследовать и другие методы.

Есть над чем поработать.
Ждем продолжения.
Пока это топик для WiKi. До статьи не дотягивает.
Нужно еще поработать.

Цитата(Sunr1se @  27.5.2006,  15:58 Найти цитируемый пост)
To moderators: пожалуйста, закрепите тему. 
Я не могу фиксировать все темы.
Шапка не резиновая. Там и так много топиков.
Если заметили, я не крепил не свою статью, ни Quadr0. 
PM MAIL   Вверх

Дата 27.5.2006, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата
Sunr1se *   Репутация: 6  Всего: 13 
Snowy, огромное спасибо за критику. Обязательно рассмотрю те моменты, которые ты указал, и исправлю ошибки. 
Цитата(Snowy @  27.5.2006,  16:32 Найти цитируемый пост)
Ждем продолжения.

Постараюсь, чтобы получилось что-то полезное...
Еще раз спасибо! 
PM MAIL ICQ   Вверх

Дата 27.5.2006, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата
Poseidon ****   Репутация: 53  Всего: 133 
Цитата(Snowy @  27.5.2006,  16:32 Найти цитируемый пост)
Я не могу фиксировать все темы.
Шапка не резиновая. Там и так много топиков.
Если заметили, я не крепил не свою статью, ни Quadr0. 
 Мне кажется статьи и не стоит закреплять. Достаточно их в FAQ добавлять 
PM MAIL ICQ   Вверх

Дата 28.5.2006, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата
Sunr1se *   Репутация: 6  Всего: 13 
Еще один вариант - создать одну фиксированную тему и в ней оставлять ссылки на статьи раздела. Тогда статьи теряться не будут...  
PM MAIL ICQ   Вверх

  
 
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0697 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.