Tyiast子组件属性到ini文件

Sco*_*ard 1 delphi delphi-xe2 firemonkey

我目前在组件属性的类型转换方面遇到了严重的问题.

在我的表格上,我有一个名为"场景"的TPanel.同样在表单上,​​我有一个创建一个按钮TSelection,然后在其中TSelection创建一个TImage然后将图片加载到该TImage中.TSelection的名称通过称为"ImgObjName"的TEdit分配.然后它将此名称写入inifile.TSelection的事件被分配给代码中其他位置的过程.如您所知,TSelection组件可以在运行时移动(并调整大小).当TSelection打开时,TImage关闭了它的HitTest.

上面的工作正如我所希望的那样,但下一部分是我被困住的地方.本质上,在计时器上,我想将每个子组件的一些属性写入TMemIniFile.有两种方式我愿意这样做;
1)写下每个孩子的属性以分开TMemInifiles.
2)将每个子项的属性写入单个TMemIniFile,但要section确定该部分中的值与哪个组件相关.

我尝试了一些不同的方法,但所有这些方法都给我带来了一些重大问题(通常是"索引越界").

我目前的方法是这样的;

ChgPos是一个全局布尔变量,当其中一个TSelection对象上的mousedown事件触发时为TRUE,当触发MouseUp事件时为FALSE.这个布尔过程非常适合这些目的,因此不需要进行任何更改.

TimerBarTTrackBar在设计时创建的.它的值根据计时器而变化.

AnimIni是早先在代码中分配的TMemIniFile.为此,我将其设置为不释放文件(因为没有访问冲突).

var
  i: Integer;
  PosX, PosY: Integer;
begin
  for i := 0 to Scene.ChildrenCount - 1 do
  begin
    if Scene.Components[i] is TSelection then
    begin
      PosX := AnimIni.ReadInteger(IntToStr(Round(TimerBar.Value)) + '_Object' +
        IntToStr(i), 'PosX', PosX);
      PosY := AnimIni.ReadInteger(IntToStr(Round(TimerBar.Value)) + '_Object' +
        IntToStr(i), 'PosY', PosY);
    end;
  end;
  if ChgPos = False then
  begin
    if Scene.Components[i] is TSelection then
    begin
      (Scene.Components[i] as TSelection).Position.X := PosX;
      (Scene.Components[i] as TSelection).Position.Y := PosY;
    end;
  end
  else if ChgPos = True then
  begin
    AnimIni.WriteInteger(IntToStr(Round(TimerBar.Value)) + '_Object' +
      IntToStr(i), 'PosX', Round((Scene.Children[i] as TSelection).Position.X));
    AnimIni.WriteInteger(IntToStr(Round(TimerBar.Value)) + '_Object' +
      IntToStr(i), 'PosY', Round((Scene.Children[i] as TSelection).Position.Y));
  end;
end;
Run Code Online (Sandbox Code Playgroud)

我正在努力弄清楚要去哪里.我正在使用它获得"索引超出范围"错误.我还需要保存TImage组件属性(特别是父级和位图位置,但我觉得让代码至少使用一个组件对我来说很重要).

我对于类型转换有点新手(因为我以前的所有项目都没有使用它),但到目前为止,我所有的经验都取得了成功.只是在这种特殊情况下,事实证明,如果没有一些帮助,我会变得更加复杂.

我确实试过WriteComponentReadComponent使用多个文件来实时传输与TimerBar值相关的数据,但是对于我想要实现的东西来说,它太慢了(特别是在写入函数上).inifile方法确实可以在我之前的测试中运行,但它实际上是在运行时创建的多个组件的类型转换,我遇到了问题.

任何人都可以对潜在的解决方案或我应该进入的方向有所了解吗?

NGL*_*GLN 6

  1. 你正在混合组件和儿童.如果遍历面板的所有子项,请不要在Components属性上使用该索引,而是使用Children属性.(我假设你的代码编译和XE2拥有Children财产,否则我想你的意思ControlsControlCount).
  2. 就像LU RD已经评论过的那样,你在for循环i之外使用for循环变量.我相信你想要它.编译器也会警告您:

    循环后,FOR循环变量'i'可能未定义

    始终确保你没有!编译器错误,警告和提示.

  3. 我不明白你的常规逻辑,因为它加载设置,即使你真的想写它们.我认为你只想在ChgPos假的情况下从MemIniFile加载设置.

没有保证,但我认为例程应该是这样的(包括一些语法改进):

var
  i: Integer;
  Selection: TSelection;
  PosX, PosY: Integer;
begin
  for i := 0 to Scene.ChildrenCount - 1 do
    if Scene.Children[i] is TSelection then
    begin
      Selection := Scene.Children[i] as TSelection;
      if ChgPos then
      begin
        AnimIni.WriteInteger(IntToStr(Round(TimerBar.Value)) + '_Object' +
          IntToStr(i), 'PosX', Round(Selection.Position.X));
        AnimIni.WriteInteger(IntToStr(Round(TimerBar.Value)) + '_Object' +
          IntToStr(i), 'PosY', Round(Selection.Position.Y));
      end
      else
      begin
        PosX := AnimIni.ReadInteger(IntToStr(Round(TimerBar.Value)) +
          '_Object' + IntToStr(i), 'PosX', PosX);
        PosY := AnimIni.ReadInteger(IntToStr(Round(TimerBar.Value)) +
          '_Object' + IntToStr(i), 'PosY', PosY);
        Selection.Position.X := PosX;
        Selection.Position.Y := PosY;
      end;
    end;
end;
Run Code Online (Sandbox Code Playgroud)

虽然我严重怀疑AnimIni.ReadInteger函数的默认值,PosX并且PosY,它们是未分配的.如果发现在ini文件中没有部分,然后PosXPosY会有任意值.你应该将它们初始化为任何有意义的东西.