Tyiast子组件属性到ini文件

时间:2012-03-31 04:36:39

标签: 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。这个布尔过程非常适合这些目的,因此不需要进行任何更改。

TimerBar是在设计时创建的TTrackBar。这是基于计时器的价值变化。

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;

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

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

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

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

2 个答案:

答案 0 :(得分:6)

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

      

    循环变量'i'可能在循环

    之后未定义

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

  3. 我不明白你的常规逻辑,因为它加载设置,即使你真的想写它们。我认为您只想在ChgPos为假时加载MemIniFile中的设置。
  4. 没有给出任何保证,但我认为例程应该如下(包括一些语法改进):

    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;
    

    虽然我严重怀疑AnimIni.ReadInteger函数的默认值,PosXPosY是未分配的。如果找不到ini文件中的部分,则PosXPosY将具有任意值。你应该将它们初始化为任何有意义的东西。

答案 1 :(得分:3)

您的循环计数器和索引属性不匹配。 ComponentCountComponents[]齐聚一堂。并ChildrenCountChildren[]在一起。您希望使用后一对,因为您对控件的子项感兴趣。 ComponentCountComponents[]属性是指所有权,这是一个不同的概念。

你的循环结束了什么,但你继续在循环变量之后使用循环变量。这显然是错的。看起来它需要在循环内部并在Scene.Children[i] is TSelection测试中。

旁边ChildrenCount在语法上与ComponentCountControlCount不一致。此属性应该已命名为ChildCount