1

我想在VerticleScrollBar. 预览项目将有一个TRectangleanTImage和一个TLabel

我的表单包含三个按钮btnLoad btnAddbtnClear.

单击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; 

更新

预览项目的创建都在工作,但是当我尝试使用 btnDelete 从 ScrollBar 中删除项目时,它会引发Index Out of bound错误Sl.Delete(j)

为什么它不StringList从该索引中删除字符串?

我怎样才能正确处理这个操作?

更新 1

我如何TImageTRectanglePreviewItems访问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; 
4

2 回答 2

2
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; 

您出现越界错误的原因是 StringList 为空。您正在为列表使用全局变量,但每次都为其分配一个新实例。

考虑在 MainForms 构造函数中创建一次字符串列表,然后在表单的析构函数中释放它。

最后一个简单的调试会让你看到这一点。考虑现在和继续这样做。

于 2019-07-11T20:34:52.097 回答
1

我认为 mRect 的 Owner 应该是 VertScroll,而不是 Form3,所以请改成这样:

mRect:= TRectangle.Create(VertScroll);

在 btnClearClick 中删除j变量并在您现在拥有j的地方简单地使用0

此外,您没有任何理由使用 TStringList,您创建它只是为了销毁/释放它。删除 SL 变量,只使用 ListBox1.Items (或解释为什么您希望 SL 成为 ListBox1.Items 的副本)

于 2019-07-11T14:27:26.200 回答