Введите свойства дочернего компонента в ini-файл - PullRequest
1 голос
/ 31 марта 2012

У меня сейчас сильная головная боль с типизацией свойств компонентов.

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

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

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

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

ChgPos - это глобальная логическая переменная, которая имеет значение ИСТИНА, когда событие mousedown на одном из объектов TSelection является пожаром, и ЛОЖЬ, когда событие 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 (в частности, местоположение родителя и растровое изображение, но я чувствую, что для меня важно, чтобы код работал с хотя бы одним компонентом на данный момент).

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

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

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

Ответы [ 2 ]

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

    Переменная цикла FOR 'i' может быть неопределенной после цикла

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

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

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

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

3 голосов
/ 31 марта 2012

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

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

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

...