Создавайте, а затем уничтожайте TLabels во время выполнения в Firemonkey.

Я пытаюсь сгенерировать TLabels во время выполнения в VertScrollBox с этим кодом;

var
   i, f: integer;
   RT_Label: TLabel;
begin
   f:= 10;
   for i := 0 to 20 do
   begin
        RT_Label := TLabel.Create(Self);
        RT_Label.Name := 'Label' + i.ToString;
        RT_Label.Text := 'SampleLabel' + i.ToString;
        RT_Label.Position.Y := f;
        RT_Label.Align := TAlignLayout.Top;
        RT_Label.Parent := VertScrollBox1;
        inc(f, 15);
   end;
end; 

Ярлыки отображаются без проблем, но когда я пытаюсь освободить сгенерированные ярлыки с помощью этого кода;

var
   i: integer;
   LComponent: TComponent;
begin
   for i := 0 to ComponentCount-1 do
   begin
        if( Components[i] is TLabel )then
         if StartsText('Label', (Components[i] as TLabel).Name) then
         begin
             LComponent := (Components[i] as TLabel);     
             If Assigned(LComponent) then FreeAndNil(LComponent);
         end;
    end;
end;

Тогда я всегда получаю ошибку "Аргумент вне диапазона". Кто-нибудь может мне помочь с этим?, Большое спасибо и привет.

1 ответ

Решение

Вы начинаете свой цикл со следующей строки

for i := 0 to ComponentCount-1 do

но когда вы освобождаете компонент, он удаляет себя из списка компонентов как часть кода очистки. Таким образом, каждый освобождаемый компонент уменьшает размер списка на 1. ComponentCount-1 Выражение вычисляется один раз, когда начинается цикл for и, следовательно, не обновляется, чтобы отразить изменение.

Даже если бы вы могли это исправить, ваш цикл будет пропускать элементы. Т.е. если бы вы удалили элемент 3, элемент 4 теперь стал бы элементом 3, но ваш цикл переместился бы к пункту 4.

Однако обойти это просто. Просто переберите список в обратном направлении:

для i:= ComponentCount-1 до 0 сделать

Стоит отметить, что ваш код будет на самом деле только бесплатные элементы в Windows и OSX. На мобильных устройствах компилятор использует ARC, который освобождает объект только после удаления всех ссылок. Решение / обходной путь /fudge[1] состоит в том, чтобы вызывать DisposeOf вместо Free для компонентов.

Помимо этого, as Оператор уже гарантирует, что объект назначен, поэтому нет необходимости в дополнительном тесте. Нет необходимости в FreeAndNil локальной переменной, которая будет либо переназначаться, либо выходить из области видимости, и нет необходимости приводить объект перед его освобождением. Поскольку метод Free (или DisposeOf) присутствует в классе общего предка, компилятор разрешит ссылки для любых классов-потомков.

Таким образом, ваш код может быть упрощен до

var
   i: integer;
begin
   for i := ComponentCount-1 downto 0 do
   begin
        if( Components[i] is TLabel )then
         if StartsText('Label', (Components[i] as TLabel).Name) then
           Components[i].DisposeOf;
   end;
end;

[1] - в зависимости от того, с кем вы разговариваете.

Другие вопросы по тегам