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.这个布尔过程非常适合这些目的,因此不需要进行任何更改.
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;
Run Code Online (Sandbox Code Playgroud)
我正在努力弄清楚要去哪里.我正在使用它获得"索引超出范围"错误.我还需要保存TImage组件属性(特别是父级和位图位置,但我觉得让代码至少使用一个组件对我来说很重要).
我对于类型转换有点新手(因为我以前的所有项目都没有使用它),但到目前为止,我所有的经验都取得了成功.只是在这种特殊情况下,事实证明,如果没有一些帮助,我会变得更加复杂.
我确实试过WriteComponent并ReadComponent使用多个文件来实时传输与TimerBar值相关的数据,但是对于我想要实现的东西来说,它太慢了(特别是在写入函数上).inifile方法确实可以在我之前的测试中运行,但它实际上是在运行时创建的多个组件的类型转换,我遇到了问题.
任何人都可以对潜在的解决方案或我应该进入的方向有所了解吗?
Components属性上使用该索引,而是使用Children属性.(我假设你的代码编译和XE2拥有Children财产,否则我想你的意思Controls和ControlCount).就像LU RD已经评论过的那样,你在for循环i之外使用for循环变量.我相信你想要它.编译器也会警告您:
循环后,FOR循环变量'i'可能未定义
始终确保你没有!编译器错误,警告和提示.
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文件中没有部分,然后PosX和PosY会有任意值.你应该将它们初始化为任何有意义的东西.