Правильный способ справиться с удалением компонентов во время выполнения? - PullRequest
0 голосов
/ 11 июля 2019

Я хочу создать PreviewList в VerticleScrollBar.Элемент предварительного просмотра будет иметь TRectangle и TImage и TLabel.

Моя форма содержит три кнопки btnLoad btnAdd и btnClear.

в btnLoad Нажмите, я загружаю изображение в Image1:

procedure TForm3.btnLoadClick(Sender: TObject);
begin
if OpenDialog1.Execute then
   Image1.Bitmap.LoadFromFile(OpenDialog1.FileName);
end; 

вbtnAdd Нажмите, я добавляю PreviewItem к VertScroll и добавляю строку к StringList, которая будет использоваться для печати изображений (еще не реализовано):

procedure TForm3.btnAddClick(Sender: TObject);
var
mRect: TRectangle;
mbit: TBitmap;
mImage: TImage;
mTitle: TLabel;
mDeleteBtn: TButton;
begin
  SL:= TStringList.Create;

  mRect:= TRectangle.Create(VertScroll);
  mRect.Height:= 60 ;
  mRect.Align:= TAlignLayout.Top;
  mRect.Margins.Bottom:= 2;
  mRect.Position.Y:= I * mRect.Height;
  mRect.Parent:=VertScroll;

  mBit:= TBitmap.Create;
  mBit.Height:= Image1.Bitmap.Height;
  mBit.Width:= Image1.Bitmap.Width;
  mBit.CopyFromBitmap(Image1.Bitmap);

  mImage:= TImage.Create(mRect);
  mImage.Parent:= mRect;
  mImage.Align:= TAlignLayout.Top;
  mImage.Height:= 50;
  mImage.Bitmap.Assign(mBit);
  mImage.WrapMode:= TImageWrapMode.Tile;
  mImage.OnClick:= mImageClick;

  mTitle:= Tlabel.Create(mRect);
  mTitle.Parent:= mRect;
  mTitle.Align:= TAlignLayout.Bottom;
  mTitle.Text:= 'Image'+ IntToStr(i);
  mTitle.Height:=10;

  mDeleteBtn:= TButton.Create(mImage);
  mDeleteBtn.Parent:= mImage;
  mDeleteBtn.Width:= 20;
  mDeleteBtn.Height:=20;
  mDeleteBtn.Text:= 'X';
  mDeleteBtn.OnClick:= btnDeleteClick;

  I:= I + 1;
  SL.Add(mTitle.Text);
  ListBox1.Items.AddStrings(SL);
  Sl.Free;
end; 

на btnClear Я очищаювсе по-новому:

procedure TForm3.btnClearClick(Sender: TObject);
var
j: integer;
begin
  SL:= TStringList.Create;
  Sl.Clear;
  SL.Free;
  for j := VertScroll.ComponentCount - 1  downto 0 do
begin
  if (VertScroll.Components[j] is TRectangle) then
  begin
    (VertScroll.Components[j] as TRectangle).Free;
  end;
end;
  ListBox1.Clear;
  I:= 0;
end; 

на mDeleteButton Нажмите, я пытаюсь удалить компонент с полосы прокрутки и удаление строки из StringList:

procedure TForm3.btnDeleteClick(Sender: TObject);
var
j: integer;
begin
  VertScroll.BeginUpdate;
  SL:=TStringList.Create;
  j:= TButton(Sender).Parent.Parent.Index;
  sl.Delete(j);
  ListBox1.Items.AddStrings(SL);
  TButton(Sender).Parent.Parent.Destroy;
  VertScroll.EndUpdate;
end; 

Обновление

Создание элемента предварительного просмотра все работает, но когда я пытаюсь удалить элементы из ScrollBar с помощью btnDelete, возникает Index Out of bound ошибка Sl.Delete(j)

, почему он не удаляет StringList строка из этого индекса?

Как я могу правильно обработать эту операцию?

Обновление 1

Как получить доступ к TImage из TRectangle в PreviewItems of VertScroll это текущий код, который я пытаюсь:

    for k := 0 to TRectangle(VertScroll.Components[j]).ChildrenCount - 1 do
        begin
          if TRectangle(VertScroll.Components[j]).Children[k] is TImage then
          begin
            img.Bitmap.Assign(TImage(TRectangle(VertScroll.Components[j]).Children[k]).Bitmap);
          end;
        end; 

Ответы [ 2 ]

2 голосов
/ 11 июля 2019
procedure TForm3.btnDeleteClick(Sender: TObject);
var
j: integer;
begin
  VertScroll.BeginUpdate;
  SL:=TStringList.Create; // You create an empty stringlist here i.e Count = 0
  j:= TButton(Sender).Parent.Parent.Index;
  sl.Delete(j); // You are telling your code to delete from an empty stringlist
  ListBox1.Items.AddStrings(SL);
  TButton(Sender).Parent.Parent.Destroy;
  VertScroll.EndUpdate;
end; 

Причиной возникновения ошибки out of out является то, что StringList пуст.Вы используете глобальную переменную для списка, но продолжаете каждый раз назначать ему новый экземпляр.

Попробуйте создать список строк один раз в конструкторе MainForms и освободите его в деструкторе формы.

Наконец-то простая отладка позволила бы вам это увидеть.подумайте о том, чтобы идти этим путем сейчас и дальше.

1 голос
/ 11 июля 2019

Я считаю, что владельцем mRect должен быть VertScroll, а не Form3, поэтому, пожалуйста, измените его на:

mRect:= TRectangle.Create(VertScroll);

В btnClearClick удалите j переменную и просто используйте 0 в местах, где у вас сейчас j .

Кроме того, вы используете TStringList без какой-либо причины, вы создаете его просто для его уничтожения / освобождения.Удалите переменную SL, просто используйте ListBox1.Items (или объясните, почему вы хотите, чтобы SL был копией ListBox1.Items)

...