Консультация № 182618
25.03.2011, 08:11
67.22 руб.
0 4 2
Добрый день, уважаемые эксперты! Буде добры и подскажите мне как работать с TComponentList... я так понимаю - это массив указателей на компонентs. Как узнать имя компонента находящегося в данном массиве (к примеру Button1), как узнать есть ли компонент в массиве а если есть то узнать его индекс.. Заранее благодарю..

Обсуждение

Неизвестный
25.03.2011, 10:22
общий
это ответ
Здравствуйте, Посетитель - 367345!
Для доступа к элементу списка TComponentList предложу следующий способ:

Код:

var
Comp1,Comp2,Comp3: TComponent;
List: TComponentList;
begin
//создаем объект класса TComponentList
List := TComponentList.Create;

//заносим в список необходимые компоненты (3 кнопки)
List.Add(Button1);
List.Add(Button2);
List.Add(Button3);

//получаем необходимый компонент по индексу
Comp1 := List.Items[0] as TComponent;
Comp2 := List.Items[1] as TComponent;

//выводим сообщение о свойствах компонента
ShowMessage ('List[0]: ' + Format (
'%s (%s): %s (%s)',
[Comp1.Name, Comp1.ClassName,
Comp1.Owner.Name, Comp1.Owner.ClassName]));
ShowMessage ('List[1]: ' +Format (
'%s (%s): %s (%s)',
[Comp2.Name, Comp2.ClassName,
Comp2.Owner.Name, Comp2.Owner.ClassName]));

//находим индекс компонента Button3 в списке List и используя полученный индекс выводим свойства компонента
Comp3:=List.Items[List.IndexOf(Button3)] as TComponent;
ShowMessage ('Button3: ' +Format (
'%s (%s): %s (%s)',
[Comp3.Name, Comp3.ClassName,
Comp3.Owner.Name, Comp3.Owner.ClassName]));


Безусловно, доступ к компонентам в списке (по индексу) можно организовать с помощью цикла и обращаться можно ко всем доступным свойствам полученного компонента.

Успехов!
5
тот пример который вы мне приводите я уже видел.. http://www.kansoftware.ru/?tid=1763 . меня в данном вопросе интересует следующее: обязательно ли передавать Comp1 := List.Items[0] as TComponent; а потом уже работать с Comp1? или можно делать так (List.Items[0] as TComponent).Name - можно ли таким образом узнать имя компонента?
давно
Мастер-Эксперт
425
4118
25.03.2011, 10:56
общий
это ответ
Здравствуйте, Посетитель - 367345!

Действительно, TComponentList является списком, аналогом динамического массива, в котором могут хранится объекты класса TComponent или наследники этого класса. Для примера, все визуальные компоненты (типа TButton, TCheckBox и т. п.) являются наследниками TСomponent.
В каких случаях можно использовать этот компонент? Представим такую ситуацию: Вы создали некую форму с кнопками (TButton), причём количество кнопок у Вас зависит от неких внешних факторов и может от случая к случаю быть разным. Как поступить? Если мы знаем, какое количество кнопок у нас должно быть максимум, то можно в процессе разработки формы поместить весь этот максимум кнопок на форму и лишние просто делать невидимыми. А если мы этот максимум не знаем? Тогда придётся заводить динамический массив и в процессе работы программы переопределять его размер и в ячейки массива заносить кнопки. Неудобно? Вне всякого сомнения. Много лишних действий. Компонент TComponentList как раз от таких лишних действий нас избавляет, предоставляя удобные формы добавления, удаления и просмотра компонентов.
Добавление компонентов осуществляется с помощью метода Add():
Код:
Var
cl: TComponentList;
...

Begin
...
For i:=0 To КоличествоКомпонентов-1 Do
Begin
cl.Add(TButton.Create(Form1));
cl[cl.Count-1].Owner:=Form1;
TButton(cl[cl.Count-1]).Top:=...;
TButton(cl[cl.Count-1].Left):=...;
...
End;
End;

Как можно обращиться к определённому компоненту? Точно так же, как к элементу массива - по его индексу.
TButton(cl[ИндексКомпонента]).Свойство:=...;
При этом упрощается поиск значения в одном из компонентов:
Код:
For i:=0 To cl.Count-1 Do
If Pos('ИскомоеЗначение', TButton(cl[i]).Caption)>0 Then
//Компонент, содержащий искомое значение, найден
Else
//Компонент не найден;

Как удалить компонент из списка? С помощью метода Remove():
Код:
cl.Remove(cl[i]);

где i - это индекс компонента найденый, например, с помощью предыдущего метода. При этом, если свойство ComponentList.OwnsObjects = True, то компонент удаляется не только из списка, но и из памяти и больше не существует.
Кроме Remove(), усть ещё и метод Extract():
Код:
cl.Extract(cl[i]);

При этом компонент просто удаляется из списка, но остаётся в памяти. Учтите, если компонент создавался с помощью метода из примера 1 и не имеет собственного имени, то доступ к нему теряется и он просто занимает память, но делать с ним ничего уже нельзя. Поэтому будьте внимательны.
Кроме обращения к конкретному компоненту по его индексу, можно непосредственно взять первый или последний компонент списка с помощью методов First или Last.
Если у каждого компонента в списке есть собственное имя, то его индекс можно узнать с помощью метода IndexOf(ИмяКомпонента).
Удаляется список из памяти с помощью стандартного метода Free(). При этом, если свойство ComponentList.OwnsObjects = True, то из памяти также удаляются и все содержащиеся в списке компоненты.
5
благодарю Вас, sir Henry, за исчерпывающий ответ... Вы как всегда как всегда достаточно полно излагаете суть проблемы.. (и у меня закрадываются смутные сомнения что вы работаете преподавателем -D). но меня ещё интересует вот что: чем отличается TButton(cl[i]) от (cl[i] as TButton)? И ещё из первого ответа: если я сделаю так Comp1 := List.Items[0] as TComponent то я получается работаю непосредственно с компонентом который находиться в List.Items[0] и с его свойствами и методами через Comp1? или мне все таки придется заново перезаписывать в List.Items[0] компонент Comp1?
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
25.03.2011, 11:23
общий
Комментарий к оценке: тот пример который вы мне приводите я уже видел.. http://www.kansoftware.ru/?tid=1763 . меня в данном вопросе интересует следующее: обязательно ли передавать Comp1 := List.Items[0] as TComponent; а потом уже работать с Comp1? или можно делать так (List.Items[0] as TComponent).Name - можно ли таким образом узнать имя компонента?


безусловно не обязательно.
пример:
Код:

if (List.Items[0] as TComponent).Name=Button1.Name then (List.Items[0] as TButton).Caption:='NEW CAPTION';


творить можно все что угодно
давно
Мастер-Эксперт
425
4118
25.03.2011, 12:45
общий
и у меня закрадываются смутные сомнения что вы работаете преподавателем

Вы не угадали. Я - скромный слесарь-сантехник.
чем отличается TButton(cl[i]) от (cl[i] as TButton)

Только синтаксисом. Обе конструкции выполняют одно и то же - представляют некий объект как экземпляр класса типа TButton.
если я сделаю так Comp1 := List.Items[0] as TComponent то я получается работаю непосредственно с компонентом который находиться в List.Items[0] и с его свойствами и методами через Comp1?

Да, Вы работаете с тем компонентом, который находится в списке. Просто Вы создаёте дополнительную переменную и присваиваете ей адрес объекта из списка. Таким образом Вы обращаетесь и в том и в другом случае к объекту с одним и тем же адресом, т.е. к одному и тому же объекту.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Форма ответа