【问题标题】:Correct way to add Items to Verticle List?将项目添加到垂直列表的正确方法?
【发布时间】:2019-07-11 10:27:33
【问题描述】:

我想在VerticleScrollBar 中创建 PreviewList。预览项目将具有 TRectangleTImageTLabel

我的表单包含三个按钮 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 中删除项目时,它会在 Sl.Delete(j) 上引发 Index Out of bound 错误

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

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

更新 1

如何在 VertScroll 的 PreviewItems 中从 TRectangle 访问 TImage 这是我正在尝试的当前代码:

    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; 

【问题讨论】:

  • 为什么要创建一个 TStringList 并在使用后立即释放它?好像你根本不需要 TStringList
  • @GuidoG Hii 这是人为错误。但将使用字符串列表打印在 vertscroll 的 previewitems 中的图像,因为我说打印部分尚未实现。我已经更新了我的问题,请看一下。

标签: delphi firemonkey delphi-10.3-rio


【解决方案1】:
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 构造函数中创建一次字符串列表,然后在表单的析构函数中释放它。

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

【讨论】:

  • 哎呀!才意识到这一点。还有一件事可以告诉我如何从VertScroll 中的TRectangle 访问TImages 我的意思是从VertScroll 栏中的previewitems 访问Timages,这样我就可以使用这些位图我已经更新了问题请看一下它。
  • @John 我认为您将不得不通过使用主窗体的 Children 属性或 VertScroll(如果有的话)来使用查找组件。见this。最后请停止编辑问题并更改其上下文。考虑问一个新的。只要遵守How to Ask 规则,人们就会很乐意回答您的所有问题。
  • @NasreddineGalfout 为什么你打电话给Destroy而不是Free
  • @Sami 因为它不是我的代码。那个代码不是我写的,是 OP 写的。我复制它作为报价。
【解决方案2】:

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

mRect:= TRectangle.Create(VertScroll);

在 btnClearClick 中删除 j 变量,然后在您现在有 j 的地方简单地使用 0

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

【讨论】:

  • 感谢您的回答。但这对我没有多大帮助。对于StringList,正如我所说,打印部分尚未实现,所以现在我使用字符串列表来更新列表框只是为了查看它是否工作。请查看更新后的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2021-10-16
  • 2021-04-28
  • 2021-01-29
  • 2019-06-15
  • 1970-01-01
相关资源
最近更新 更多