Цикл по ВСЕМ контролам

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Цикл по ВСЕМ контролам

Сообщение Troublemaker » 25.05.2008 20:59:42

Не могу сообразить, как же пройтись по ВСЕМ контролам, скажем, TTabSheet-a, в том числе и тем, которые в подчиненных боксах и панелях. Разве что делать обход по принципу дерева каталогов?

Зачем надо? Ну, хочу, например, чтобы у всех edit-ов в hint добавилась их максимальная длина - при вписывании ее вручную можно потом забыть исправить, если она изменится.
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Цикл по ВСЕМ контролам

Сообщение alexs » 25.05.2008 22:13:56

Код: Выделить всё
  for I:=0 to Form1.ControlCount-1 do;
    Form1.Controls[i].Hint:='bla-bla';
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Цикл по ВСЕМ контролам

Сообщение Troublemaker » 25.05.2008 23:40:12

А вот ни фига!
Прежде чем ответить специально проверил: так находятся только контролы, подчиненные самой форме, но не те, что подчиняются ее подчиненным. Например, мне не удалось таким способом добраться до радиокнопок в радиобоксе. Конкретно по моей форме (см. рисунок) находятся всего четыре контрола: пейджконтрол, статусбар, тулбар и прогресс (маленький прямоугольник в правой части тулбара).

Так что вопрос остается в силе: как посмотреть контролы, подчиненные не самой форме?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Цикл по ВСЕМ контролам

Сообщение B4rr4cuda » 26.05.2008 01:05:26

Код: Выделить всё
for i:=0 to GroupBox1.ControlCount-1 do
if GroupBox1.Controls[i] is TLabel then
(GroupBox1.Controls[i] as Tlabel).Caption:='1';   
:)

Если нужно пройти все контролы, в том числе находящиеся на панелях или групбоксах, то пишем рекурсивную функцию проходящую все контролы формы и передающую их в качестве параметра этой же функции, для поиска подчиненных контролов.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Цикл по ВСЕМ контролам

Сообщение Troublemaker » 26.05.2008 02:16:09

B4rr4cuda писал(а):пишем рекурсивную функцию

Так я и знал :)
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Цикл по ВСЕМ контролам

Сообщение VirtUX » 26.05.2008 16:31:17

у меня все контролы проходятся. При чем мне приходится специально выделять те которые на Panelи if (Form1.Components[i] as TControl).Parent = Panel1 then .... А в RadioGrupBox и ему подобных контрлы созданы (скорее всего) в них, а не в форме, т.е. RadioButton := RadioButton.Create(RadioGrupBox); RadioButton.Parent := RadioGrupBox;. Самый верный выход из положения видится, если RadioButton-ы создавать на отдельных панелях, а не в GrupBox-ах. Тогда он будет определяться в массиве контрлов принадлежащих Form-е и управляемый Panel-ью.
Попробуй использовать:
for i := 0 to pred(TForm1.ComponentCount) do
(Form1.Components[i] as Tcontrol).AnyWhat := AnyWhat;
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Цикл по ВСЕМ контролам

Сообщение Troublemaker » 26.05.2008 17:23:03

VirtUX писал(а):у меня все контролы проходятся
Контролы или компоненты?

Кажется понял, в чем дело. На этой конкретной форме насчиталось 4 контрола и 98 компонентов. Цикл по form.components дал мне то, что я хотел, вроде бы...

Вот именно, что "вроде" - в "инспекторе объектов" как раз 98 штук и насчитал. В это число не вошли созданные в рантайме пара десятков радиокнопок :(
(смотрел в методе OnShow, когда эти кнопки уже созданы)

Добавлено спустя 3 минуты 52 секунды:
Разве что, при создании чего-то в рантайме вызывать form.addControl?
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Цикл по ВСЕМ контролам

Сообщение VirtUX » 26.05.2008 17:29:48

Только что проверил. RadioGroup - определяется как единый компонент. Внутренностями нужно управлять через свойства его. А вот GroupBox берет на себя только свойство Parent, поэтому все внутренности видны. Ставь RadioButton-ы в GroupBox и будет тебе счастье :)

Добавлено спустя 3 минуты 12 секунд:
Troublemaker писал(а):
VirtUX писал(а):у меня все контролы проходятся
Контролы или компоненты?

Я же написал
Код: Выделить всё
Form1.Components[i] as TСontrol
Хочешь - это будет контрол, убери as TControl будет тебе компонент.
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: Цикл по ВСЕМ контролам

Сообщение Troublemaker » 26.05.2008 18:10:21

VirtUX писал(а):Ставь RadioButton-ы в GroupBox и будет тебе счастье
Именно так и делаю. Кнопки, которые созданы в дизайнере, видны как отдельные контролы/компоненты. Те, которые созданы в рантайме, не видны.
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Цикл по ВСЕМ контролам

Сообщение alexs » 26.05.2008 20:10:32

Сам не проверял. Но всёже - а ты им имя присваиваеш уникальное? может в этом дело?
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Цикл по ВСЕМ контролам

Сообщение Troublemaker » 26.05.2008 20:28:09

alexs писал(а):имя присваиваеш уникальное?

Разумеется. Вот так, как мы когда-то обсуждали в теме "передача типа как параметра". Я не стал возиться с классами - раньше никогда сам их не делал, и боюсь сейчас "зарыться", поэтому "рулит" старое доброе процедурное программирование.

car и har - массивы строк для caption и hint.
BuName - шаблон для создания имен, например

Код: Выделить всё
procedure TEditForm.CreateButtons(car,har:TStrArray;var bar:array of TRadioButton;BuName:string;POw:TGroupBox;ONC:TNotifyEvent);
var i:Integer;
begin
  for i:=Low(car) to High(car) do begin
    bar[i]:=TRadioButton.Create(POw);
    with bar[i] do begin
      Caption:=car[i];
      Hint:=har[i];
      Width:=cDefRButHeight;
      Height:=cDefRButHeight;
      Visible:=true;
      Tag:=ord(i);
      Name:=BuName+Format('%2.2D',[i]);
      Checked:=false;
      Parent:=POw;
      Onclick:=ONC;
      TabStop:=false;
    end;
  end;
end;


Вот примеры использования из реального исходника:
Код: Выделить всё
  CreateButtons(TStrArray(cCDKName),TStrArray(cCDKHint),CDKButtons,'CDKButton',CollDestKindBox,@CollKindChanged);

  CreateButtons(TStrArray(cQKname),TStrArray(cQKhint),QKButtons,'QKButton',QKindBox,@QKindChanged);

  CreateButtons(TStrArray(cEKname),TStrArray(cEKhint),EKButtons,'EKButton',ExamKindBox,@EKindChanged);

Соответственно, имена получаются типа CDKButton00, QKButton03 и т.п.

Единственное сомнение, ибо этот момент как-то не очень отражен в документации, это то, что я при создании указываю овнером тот групбокс, куда кнопки должны вставляться. Может там надо указывать форму как овнера, а групбокс только как родителя?

Добавлено спустя 22 минуты 56 секунд:
Сейчас изменил немного процедуру создания кнопок:
Код: Выделить всё
bar[i]:=TRadioButton.Create(EditForm);
Кнопки появились в списке компонентов формы. Но мне это не нравится.
Не нравится тем, что я в описании КЛАССА обращаюсь к конкретной переменной, не являющейся пропертью этого класса, и не могу вспомнить, к чему относится self - к экземпляру класса или к чему-то другому? То есть, если вместо Create(EditForm) я напишу Create(Self), кто станет овнером?
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Цикл по ВСЕМ контролам

Сообщение dymken » 27.05.2008 06:45:31

bar[i]:=TRadioButton.Create(EditForm);
Это как раз-таки правильно. В конструктор передается компонент-владелец (Owner). В каждом компоненте есть массив подчиненных компонентов, для которых он выступает владельцем. TForm - этот тоже компонент. Когда бросаешь компонент на форму, то Owner'ом выступает форма. Это нужно, чтобы при удалении формы, ее деструктор смог пройти по всем компонентам и освободить их.

Self указывает на текущий экземпляр, поэтому код

Код: Выделить всё
procedure TEditForm.Add;
begin
bar:=TRadioButton.Create(EditForm);
end;


Будет полностью эквивалентен:
Код: Выделить всё
procedure TEditForm.Add;
begin
bar:=TRadioButton.Create(Self);
end;


И даже правильнее, т.к. потенциально можно создать несколько экземпляров форм, а первый пример сошлется только на одну.
dymken
новенький
 
Сообщения: 11
Зарегистрирован: 10.01.2008 11:50:14

Re: Цикл по ВСЕМ контролам

Сообщение Troublemaker » 27.05.2008 11:07:52

dymken писал(а):первый пример сошлется только на одну

ВотЪ-вотЪ! Поэтому мне и не понравилось, то, что не понравилось.
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 37

Рейтинг@Mail.ru