2012-03-31 3 views
1

В настоящее время у меня сильная головная боль при типизации свойств компонента.Свойства дочерних компонентов Typecast для ini-файла

В моей форме у меня есть TPanel под названием «сцена». Также в форме у меня есть кнопка, которая создает TSelection, и в этом TSelection создает TImage, а затем загружает изображение в этот TImage. Имя TSelection присваивается с помощью TEdit, известного как «ImgObjName». Затем он записывает это имя в новшество. События для TSelection присваиваются процедурам в другом месте кода. Как вы знаете, компонент TSelection можно перемещать (и изменять размер) во время выполнения. TImage отключил HitTest, когда TSelection включился.

Вышеупомянутые работы, как я хочу, но следующая часть, где я застрял. По существу, по таймеру я хочу написать несколько избранных свойств каждого дочернего компонента в TMemIniFile. Есть два способа, которыми я готов это сделать;
1) Напишите свойства каждого ребенка для разделения TMemInifiles.
2) Напишите свойства каждого дочернего элемента в один TMemIniFile, но сделайте section определите, к какому компоненту относятся значения в этом разделе.

Я пробовал несколько разных методов, но все они вызвали у меня некоторые серьезные проблемы (обычно «индекс за пределами границ»).

Мой текущий метод как таковой;

ChgPos - глобальная логическая переменная, которая является ИСТИНА, когда событие mousedown на одном из объектов TSelection является огнем и FALSE, когда событие MouseUp запущено. Эта логическая процедура отлично работает для этих целей, поэтому никаких изменений там не требуется.

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-расположение, но я считаю, что для меня важно, чтобы код работал с хотя бы одним компонентом на данный момент).

Я несколько новичок в области машинного перевода (поскольку все мои предыдущие проекты работали без его необходимости), но все мои опыты с ним до сих пор были успешными. Именно в этом конкретном случае доказано, что он становится более сложным, чем я могу работать без какой-либо помощи.

Я попробовал WriteComponent и ReadComponent и использовал несколько файлов для передачи данных в реальном времени по отношению к значению TimerBar, но он слишком медленный для того, чего я хочу достичь (особенно в функции записи). Метод inifile работает с моим предыдущим тестированием, но на самом деле он работает с типизацией нескольких компонентов, созданных во время выполнения, с которыми у меня возникают проблемы.

Может ли кто-нибудь пролить свет на потенциальное решение или направление, в которое я должен войти?

+2

Ваш цикл i заканчивается слишком рано. Состояние i в вашем 'if ChgPos' (и остальном) не определено. –

ответ

6
  1. Вы смешиваете компоненты и детей. Если вы пропустите все дочерние элементы панели, не используйте этот индекс в свойстве Components, но свойство Children. (Я предполагаю, что ваш код скомпилирован, а XE2 имеет свойство Children, в противном случае я думаю, что вы имеете в виду Controls и ControlCount).
  2. Как и в случае с LU RD, вы используете переменную for-loop i вне цикла for. Я уверен, что ты этого хочешь. Вы также предупреждены компилятором для этого:

    для цикла переменной «I» может быть определен после цикла

    Всегда убедитесь, что у вас есть ноль! ошибки компилятора, предупреждения и подсказки.

  3. Я не понимаю вашу обычную логику, потому что он загружает настройки, даже если вы действительно хотите их записать. Я думаю, вы только хотите загрузить настройки из MemIniFile, когда ChgPos является ложным.

Нет гарантии даны, но я думаю, что процедура должна выглядеть следующим образом (в том числе несколько улучшений синтаксиса):

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, PosX и PosY, которые не назначены. Если ни один раздел в ini-файле не найден, то PosX и PosY будут иметь произвольные значения. Вы должны инициализировать их, чтобы иметь смысл.

+1

Я думаю, что свойство Children должно быть FMX. –

+0

Это именно то, что было NGLN. «Дети» - действительно свойство FMX. Как бы то ни было, не было никакого предупреждения или намека на цикл (и только на переменные, которые я не использовал из других процедур) Из-за хорошо написанного объяснения и исправления кода я должен дать этот голос ваш ответ, но поскольку несколько человек помогали, я проголосовал за каждый их ответ. –

3

Ваш счетчик циклов и индексированные свойства не совпадают. ComponentCount и Components[] вместе.И ChildrenCount и Children[] идут вместе. Вы хотите работать с последней парой, так как вы интересны детям контролей. Свойства ComponentCount и Components[] относятся к собственности, которая является другой концепцией.

Что больше подходит для вашей петли, но вы продолжаете использовать переменную цикла после переменной цикла. Это явно неправильно. Похоже, что он должен находиться внутри цикла и внутри теста Scene.Children[i] is TSelection.

В качестве альтернативы ChildrenCount также грамматически не определен ComponentCount и ControlCount. Это свойство должно было называться ChildCount.

Смежные вопросы