1

我将一些图像加载到对象列表中,然后尝试调用它们。但它不显示图像?

procedure TForm1.LoadImages(const Dir: string);
var
  i: Integer;
  CurFileName: string;
  JpgIn: TJPEGImage;
  BmpOut: TBitmap;
begin
//sets index for object list
  CurIdx := -1;
  i := 0;
  while True do
  begin
//gets current folder 
    CurFileName := Format('%s%d.jpg',
                          [IncludeTrailingPathDelimiter(Dir), i]);
    if not FileExists(CurFileName) then
      Break;
//creates jpgin
    JpgIn := TJPEGImage.Create;
    try
//loads jpgin 
      JpgIn.LoadFromFile(CurFileName);
//creates TBitmap and sets width to same as jpgs
      BmpOut := TBitmap.Create;
      bmpout.Width := jpgin.Width;
      bmpout.Height := jpgin.Height;
     try
         BmpOut.Assign(JpgIn);
//if i assign it here it works, showing last image of course
         //zimage1.Bitmap.Width := bmpout.Width;
        //zimage1.Bitmap.Height := bmpout.Height;
         //ZImage1.Bitmap.Assign(bmpout);
//adds 1 to index for object list. thus starting at 0
         curIdx := curIdx+1;
//add bitmap to objectlist
         CurIdx:= mylist.Add(TBitmap(bmpout));
      finally
//free bitmap and jpg
        BmpOut.Free;
      end;
    finally
      JpgIn.Free;
    end;
    Inc(i);
  end;
//makes sure cout is above 0  
  if mylist.Count > 0 then
  begin
//create bitmap
    BmpOut := TBitmap.Create;
      try
//sets width and heigh of bitmap before getting image
      bmpout.Height := TBitmap(mylist[curidx]).Height;
      bmpout.Width := TBitmap(mylist[curidx]).Width;
      bmpout.Assign(TBitmap(mylist[CurIdx]));
//sets zimage width height before getting image.
      zimage1.Bitmap.Width := bmpout.Width;
      zimage1.Bitmap.Height := bmpout.Height;
      ZImage1.Bitmap.Assign(bmpout);
    finally
      BmpOut.Free;
    end;
  end;
  page:= '0';
end;

如果你注意到我有这个部分,看看将 iamge 加载到 zimage1 中是否有问题。

     //zimage1.Bitmap.Width := bmpout.Width;
    //zimage1.Bitmap.Height := bmpout.Height;
     //ZImage1.Bitmap.Assign(bmpout);

当我这样做时,它会将 bmpout 加载到 zimage1 中,这导致我认为它与我做错的对象列表有关?

4

1 回答 1

5

你有这个代码:

  CurIdx:= mylist.Add(TBitmap(bmpout));
finally
  //free bitmap and jpg
  BmpOut.Free;
end;

您将一个项目添加到列表中,然后立即释放该项目。TList它的后代TObjectList不会对他们持有的对象进行“深拷贝”。

当您稍后阅读列表的内容时,您得到的是过时的引用。它们不再引用它们最初引用的对象,而且它们可能根本不引用任何对象。这些位置的内存可能仍然包含结构看起来像那些以前的对象的数据,但不能保证这一点。也不能保证您的程序不会崩溃。崩溃是典型的,但下一个最常见的行为是您的程序出现细微的错误,例如继续运行但不显示预期的数据。


如果你想要一个对象列表,那么不要释放它们;摆脱finally我上面引用的块。为了异常安全,您需要小心地将所有权从当前代码块转移到列表,如下所示:

BmpOut := TBitmap.Create;
try
  BmpOut.Assign(JpgIn);
  CurIdx := mylist.Add(bmpout);
except
  BmpOut.Free;
  raise;
end;

Assign如果在or调用期间发生异常Add,则本地过程应释放位图。否则,列表获得对象的所有权,释放列表将隐式释放其所有对象(假设列表的OwnsObjects属性为True)。

一旦您加载了所有位图并将它们存储在列表中,就没有真正需要创建另一个位图只是为了将某些内容分配给您的图像控件。您可以只使用您存储在列表中的那个:

if mylist.Count > 0 then
begin
  ZImage1.Bitmap.Assign(mylist[mylist.Count - 1]);
end;

从该代码中,您可以看到您甚至不需要跟踪CurIdx. 它的值将始终是最后添加的对象的索引,并且该索引将始终比列表中对象的总数小一。

您也不必在从另一个图形对象为其分配值之前设置位图的高度和宽度。它将自动获取源对象的尺寸。

于 2012-06-13T21:18:35.997 回答