Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi组件,具有可变数量的TPictures_Delphi_Vcl - Fatal编程技术网

Delphi组件,具有可变数量的TPictures

Delphi组件,具有可变数量的TPictures,delphi,vcl,Delphi,Vcl,我试图创建一个从TImage开始的组件,不同的是我可以在属性列表中分配一个可变数量的TPictures(而不是按代码分配TPictures),并按代码激活其中一个以显示在TImage中 如果有必要在属性中分配所有TPictures,那么设置TPictures总数(动态数组的长度)的属性就不会有问题 unit ImageMultiStates; interface uses Vcl.Graphics, Vcl.StdCtrls, System.SysUtils, System.Classe

我试图创建一个从TImage开始的组件,不同的是我可以在属性列表中分配一个可变数量的TPictures(而不是按代码分配TPictures),并按代码激活其中一个以显示在TImage中

如果有必要在属性中分配所有TPictures,那么设置TPictures总数(动态数组的长度)的属性就不会有问题

unit ImageMultiStates;

interface

uses
  Vcl.Graphics, Vcl.StdCtrls, System.SysUtils, System.Classes, Vcl.Controls, Vcl.ExtCtrls, Forms;

type
  TPictures = Array of TPicture;
  TImageMultiStates = class(TImage)
  private
      FPictures: TPictures;
      procedure SetPicture(Which: Integer; APicture: TPicture);
  public
      constructor Create(AOwner: TComponent); override;
      destructor Destroy; override;
      procedure Activate(Which: Integer);
  published
    property Images: TPictures read FPictures write FPictures; default;
  end;

procedure Register;

implementation

constructor TImageMultiStates.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  for TPicture in FPictures do
    TPicture := TPicture.Create;
end;

destructor TImageMultiStates.Destroy;
var
  APicture: TPicture;
begin
  for APicture in FPictures do
    APicture.Free;
  inherited Destroy;
end;

procedure TImageMultiStates.Activate(Which: Integer);
begin
  Picture.Assign(FPictures[Which]);
end;

procedure TImageMultiStates.SetPicture(Which: Integer; APicture: TPicture);
begin // i would also like to use SetPicture instead of "write FPictures"
  FPictures[Which].Assign(APicture);
  if Which=0 then // because: First Picture will be displayed in the VCL editor
    Picture.Assign(FPictures[Which]);
end;

procedure Register;
begin
  RegisterComponents('Standard', [TImageMultiStates]);
end;

end.
我在很多方面改变了这段代码,但我就是不能让任何东西真正起作用


在我的组件“Image2States”中,我已经有了完全相同的想法。然后我需要“Image4States”等等,直到我决定我绝对需要这张带有可变数量图片的图片…

我会问:你希望它做什么:

for TPicture in FPictures do
  TPicture := TPicture.Create;
首先,如前所述,这根本不需要编译。未声明TPicture循环变量(如果与类型名称相同,则即使已声明,也会导致后续编译错误)

即使假设循环是有效的可编译代码,当构造函数执行FPictures时,它也是一个空数组,因此该循环将执行0(零)次。您不会显示任何告诉组件应该支持多少图片的代码,因此它始终支持0(零)

问题还不止于此

如果您确实声明了一个合适的变量用作循环变量,那么循环代码仍然不会编译,因为它涉及到对循环变量的赋值,这是不允许的

即使在简单for循环以及基于迭代器的循环(如您尝试使用的循环)中也是如此。对于简单循环,这是为了使编译器能够生成最佳代码。在迭代器循环的情况下,它还可以保护您避免可能容易犯的错误

考虑到在这种情况下,在循环的每次迭代中,您都会创建一个新的TPicture实例并将其分配给循环变量,但这不会将其分配给初始化循环变量的数组中的项

也许解释这一点最简单的方法是“展开循环”(展开循环就是为每次迭代显式地重新编写代码,就好像根本没有循环一样)

如果循环包含2个项,那么我们也可以改变循环变量的名称,使事情既有效又清楚一些。我们将简单地使用pic。换句话说,我们将展开此循环的2个迭代版本:

for pic in FPictures do  // fPictures contains 2 items
  pic := TPicture.Create;
请记住,这是而不是编译,当我们展开它将创建的循环(如果可能的话)时,这有助于防止我们犯错误的原因变得很明显:

// Iteration #1
pic := fPictures[0];
pic := TPicture.Create;

// Iteration #2
pic := fPictures[1];
pic := TPicture.Create;
希望你能看到问题所在。在每次迭代中覆盖循环变量的值,但这不会修改数组项本身。更糟糕的是,循环的每次迭代都会泄漏一张t图片

希望这能帮助您理解为什么代码不能工作(实际上,不能工作)并进行必要的更正

  • 您需要一些机制来设置组件支持的图片数量

  • 您需要正确初始化包含这些图片的数组中的项目


  • 您告诉我们您的方法“不起作用”(我想您的意思是“未编译”):这是因为一些语法错误,并且您没有使用正确的工具来完成此工作

    如果您只有相同大小的图片,请考虑使用现有的、经过良好测试且受IDE支持的
    TImageList
    ,不要尝试重新发明轮子

    尝试 但是,如果必须有不同大小的图片列表,则使用
    TObjectList
    而不是
    图片数组。TobjectList允许您添加、删除、查询等对象,如果您愿意,它们可以自动释放这些对象

    如果编译器支持泛型,请包含System.generics.Collections,并使用
    TObjectList
    来管理图片。这样,您就不必强制转换到
    TPicture
    ,因为泛型列表是类型安全的

    如果不支持它们,则包括单元Contnrs并使用
    TObjectList
    。在阅读该列表时,您必须使用
    as
    ,即
    as TPicture
    ,否则您可以执行类似的操作

    最后 您类型的名称使我认为,对于某个控件,您只需要多个状态。在这种情况下,我认为
    TImageList
    是这项工作的最佳工具(对于其他具有类似需求的控件来说,它已经是了),并且没有必要制作自己的工具。但是如果你想自己制作,不要使用动态数组,也不要像FPictures do
    中的TPicture那样生成循环。帮自己一个忙,使用对象列表


    End您需要维护一组图片。希望您能在构造函数中创建图片实例是一个错误。@David Heffernan:哦,是的,当然。我真傻。但除此之外,我在这里尝试的东西能起作用吗?我应该在属性中设置图片数量,还是由适当的PropertyEditor正确显示一组图片?我想您应该使用包含图片对象的
    t集合。然后它应该可以很容易地连接到属性编辑器。以防万一,您确实知道
    TImageList
    ,是吗?它可以保存TImage支持的任何类型的动态大小相同的图像,并具有设计时编辑器。限制是,图像需要相同的大小,默认值是16×16,但是可以在任何图像被添加到列表之前根据需要改变高度和宽度。但是考虑使用TimaGelistor,如果YO