Перейти к содержанию
Fire Monkey от А до Я
  • 0

Удаление Item'ов из ListBox c помощью цикла while


Sashar333

Вопрос

Здравствуйте!

Есть ListBox1, на нем разное кол-во tlistboxitem'ов, на каждом tlistboxitem'е есть один tgridpanellayout состоящий из четырех колонок и одной строчи, в каждой колонке

по одному trectangle, в каждом trectangle по одному ttext с именами по очереди типа 'w'+IntToStr(Item.index), 'l'+IntToStr(Item.index), 'k'+IntToStr(Item.index)

такие имена для Ttext требуются для дальнейшей обработки и распознования, в каждом Ttext надпись, на примере "-","2","2","Х" :

5942d330166d9_.PNG.7ed637728fd90f80f0d14eabace08bdc.PNG

при нажатии на текст "Х" удаляется tlistboxitem c помощью listbox1.Items.Delete(indexclick)

Проблема следующая, при создании нового итема пишет дубликат имени Ttext, я так понял что итем удалился а то что на нем -нет

как можно быстро удалить и итем и то что на нем находилось? Пример создания итема:

procedure addrazmer(zap:typezap);
var item:tlistboxitem;
    pg:tgridpanellayout;
    t1,t2,t3,t4:ttext;
    al:talignlayout;
    r1,r2,r3,r4:trectangle;
    i:integer;
begin
form1.listbox1.BeginUpdate;
while Form1.listbox1.Count<>1 do Form1.listbox1.Items.Delete(0);

for i := 0 to length(zap.razmer)-1 do
begin
 item:=tlistboxitem.Create(form1.listbox1);
 item.Height:=30;
 pg:=tgridpanellayout.Create(item);
 pg.RowCollection[1].Value:=0;
 pg.ColumnCollection.Add;pg.ColumnCollection[2].Value:=50;
 pg.ColumnCollection.Add;pg.ColumnCollection[3].Value:=10;
 pg.Parent:=item;
 pg.Align:=al.alClient;
 r1:=trectangle.Create(pg);
 r2:=trectangle.Create(pg);
 r3:=trectangle.Create(pg);
 r4:=trectangle.Create(pg);
 r1.Parent:=pg;r1.Align:=al.alClient;
 r2.Parent:=pg;r2.Align:=al.alClient;
 r3.Parent:=pg;r3.Align:=al.alClient;
 r4.Parent:=pg;r4.Align:=al.alClient;
 t1:=ttext.Create(r1);
 if zap.tip<>'Лист' then
  Begin
   t1.Enabled:=false;
   t1.Text:='-';
  End
 else
  Begin
   t1.text:=floattostr(zap.razmer.witdh);
  end;
 t2:=ttext.Create(r2);t2.text:=floattostr(zap.razmer.length);
 t3:=ttext.Create(form1);t3.Text:=floattostr(zap.razmer.kol);
 t4:=ttext.Create(form1);t4.Text:='X';

 t1.Parent:=r1;t1.OnClick:=form1.CliskRazmerClick;
 t2.Parent:=r2;t2.OnClick:=form1.CliskRazmerClick;
 t3.Parent:=r3;t3.OnClick:=form1.CliskRazmerClick;
 t4.Parent:=r4;t4.OnClick:=form1.DeleteItemClick;

 t1.Align:=al.alClient;
 t2.Align:=al.alClient;
 t3.Align:=al.alClient;
 t4.Align:=al.alClient;
 form1.listbox1.InsertObject(form1.listbox1.Items.Count-1,item);
 t1.Name:='w'+IntToStr(item.Index);
 t2.Name:='l'+IntToStr(item.Index);
 t3.Name:='k'+IntToStr(item.Index);
end;
form1.listbox1.EndUpdate;
end; 

Заранее спасибо!

Изменено пользователем Andrey Efimov
Изменил заголовок и добавил тег "Код"
Ссылка на комментарий

Рекомендуемые сообщения

  • 1
1 час назад, Sashar333 сказал:

по одному ttext с именами по очереди типа 'w'+IntToStr(Item.index), 'l'+IntToStr(Item.index), 'k'+IntToStr(Item.index)

Для создаваемых в runtime элементов не используйте свойство name, это действительно чревато вам дубликатами. Оставляйте name пустым.

Ориентируйтесь на что угодно другое, хоть различные вариации свойства tag[Object, string]

Ссылка на комментарий
  • 1

Из приведенного выше кода ничего вручную удалять не нужно, кроме самого TListBoxItem, как и выполняется в примере выше (listbox1.Items.Delete(indexclick) или Form1.listbox1.Items.Delete(0)) . Все создаваемые дополнительные контролы (TGridPanelLayout, TRectangle, TText) создаются здесь с AOwner = TListBoxItem + задается Parent, который мы и удаляем, а при удалении родительского все дочерние удаляются вместе с ним. Можете убедиться в этом проверив утечку памяти: 

ReportMemoryLeaksOnShutdown := True;

Sashar333 не используйте никогда .Name в качестве хранилища или идентификатора, это плохая практика. Для этих целей отлично подходят тэги (TagString или TagFloat), которые имеют все TFmxObject.

 

Изменено пользователем Fedor K
добавление утечки памяти
Ссылка на комментарий
  • 0
11 час назад, Fedor K сказал:

Из приведенного выше кода ничего вручную удалять не нужно, кроме самого TListBoxItem, как и выполняется в примере выше (listbox1.Items.Delete(indexclick) или Form1.listbox1.Items.Delete(0)) . Все создаваемые дополнительные контролы (TGridPanelLayout, TRectangle, TText) создаются здесь с AOwner = TListBoxItem + задается Parent, который мы и удаляем, а при удалении родительского все дочерние удаляются вместе с ним. Можете убедиться в этом проверив утечку памяти: 


ReportMemoryLeaksOnShutdown := True;

Sashar333 не используйте никогда .Name в качестве хранилища или идентификатора, это плохая практика. Для этих целей отлично подходят тэги (TagString или TagFloat), которые имеют все TFmxObject.

 

с .Name понятно, буду переделывать, спасибо!

Но если "...а при удалении родительского все дочерние удаляются вместе с ним. Можете убедиться в этом проверив утечку памяти" почему тогда ругается на дублирование имени...

Ссылка на комментарий
  • 0
17 минут назад, Sashar333 сказал:

Но если "...а при удалении родительского все дочерние удаляются вместе с ним. Можете убедиться в этом проверив утечку памяти" почему тогда ругается на дублирование имени...

Потому что у t3 и t4 Owner - это form1:
 

 t3:=ttext.Create(form1);t3.Text:=floattostr(zap.razmer.kol);
 t4:=ttext.Create(form1);t4.Text:='X';

а значит они не удаляются при удалении item. По логике должны быть r3 и r4 соответственно.
 

 t3:=ttext.Create(r3);
 t4:=ttext.Create(r4);

 

Ссылка на комментарий
  • 0
2 часа назад, enatechno сказал:

Потому что у t3 и t4 Owner - это form1:
 


 t3:=ttext.Create(form1);t3.Text:=floattostr(zap.razmer.kol);
 t4:=ttext.Create(form1);t4.Text:='X';

а значит они не удаляются при удалении item. По логике должны быть r3 и r4 соответственно.
 


 t3:=ttext.Create(r3);
 t4:=ttext.Create(r4);

 

Небольшое уточнение: они не удаляются только на мобильных платформах, т.к. идет вызов DisposeOf:

//смотрим код в unit FMX.Types;
procedure TFmxObject.DoDeleteChildren;
...
      Child := FChildren[I];
      FChildren.Delete(I);
      Child.FParent := nil;
      Child.SetRoot(nil);
      Child.DisposeOf; // вот причина ошибки с именем на мобильных платформ, удалене контрола идет не сразу, а при обнулении ссылок
...

Для RunTime компонентов лучше в качестве Owner указывать nil и задавать лишь Parent, чтобы уменьшить кол-во ссылок и путаницы.

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...