2012-03-31 16 views
1

Ich habe derzeit große Kopfschmerzen mit Typumwandlung von Komponenteneigenschaften.Typecast untergeordnete Komponente Eigenschaften in Ini-Datei

Auf meinem Formular habe ich ein TPanel namens "Szene". Auch auf dem Formular habe ich eine Schaltfläche, die eine TSelection erstellt, und innerhalb dieser TSelection erstellt eine TImage und laden Sie dann ein Bild in diese TImage. Der Name für die TSelection wird über ein TEdit namens "ImgObjName" vergeben. Dann schreibt er diesen Namen in eine Inifile. Die Ereignisse für die TSelection werden anderen Prozeduren im Code zugewiesen. Wie Sie wissen, kann die TSelection-Komponente zur Laufzeit verschoben (und in der Größe angepasst) werden. Das TImage hat seinen HitTest ausgeschaltet, während die TSelection eingeschaltet ist.

Das oben genannte funktioniert, wie ich es will, aber der nächste Teil ist, wo ich feststecke. Im Wesentlichen möchte ich auf einen Timer einige ausgewählte Eigenschaften jeder untergeordneten Komponente in eine TMemIniFile schreiben. Es gibt zwei Möglichkeiten, wie ich dazu bereit bin;
1) Schreiben Sie die Eigenschaften jedes untergeordneten Elements in TMemInifiles.
2) Schreiben Sie die Eigenschaften jedes untergeordneten Elements in ein einzelnes TMemIniFile, aber geben Sie section an, auf welche Komponente sich die Werte in diesem Abschnitt beziehen.

Ich habe ein paar verschiedene Methoden ausprobiert, aber alle von ihnen haben mir einige große Probleme (normalerweise "Index außerhalb der Grenzen") verursacht.

Meine aktuelle Methode ist als solche;

ChgPos ist eine globale boolesche Variable, die TRUE ist, wenn das Mousedown-Ereignis für eines der TSelection-Objekte aktiviert ist, und FALSE, wenn das MouseUp-Ereignis ausgelöst wird. Diese boolesche Prozedur funktioniert perfekt für diese Zwecke, so dass dort keine Änderungen erforderlich sind.

TimerBar ist eine TTrackBar, die zur Designzeit erstellt wurde. Es ist Wert Änderungen basierend auf einem Timer.

AnimIni ist die TMemIniFile, die früher im Code zugewiesen wurde. Zu diesem Zweck habe ich festgelegt, dass die Datei nicht freigegeben wird (es gibt keine Zugriffsverletzungen).

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; 

Ich kämpfe, um herauszufinden, wohin damit zu gehen. Ich bekomme "Index außerhalb des Bereichs" Fehler damit. Ich muss auch die Eigenschaften der TImage-Komponente speichern (insbesondere die Eltern- und Bitmap-Position, aber ich denke, dass es wichtig ist, dass der Code im Moment mit mindestens einer Komponente funktioniert).

Ich bin ein wenig zu typecasting (wie alle meine früheren Projekte funktionierten, ohne es zu brauchen), aber meine ganze Erfahrung damit war bisher angenehm erfolgreich. Es ist nur in diesem speziellen Fall bewiesen, dass es komplizierter wird, als ich ohne etwas Hilfe trainieren kann.

Ich habe versucht WriteComponent und ReadComponent und mehrere Dateien verwenden, um die Daten in Echtzeit in Bezug auf den Wert von TimerBar zu streamen, aber es ist viel zu langsam für das, was ich erreichen möchte (besonders auf der Schreibfunktion). Die Inifile-Methode funktioniert nach meinen früheren Tests, aber sie arbeitet tatsächlich mit der Typumwandlung von mehreren Komponenten, die zur Laufzeit erstellt werden, mit denen ich Probleme habe.

Kann jemand etwas über eine mögliche Lösung oder die Richtung, in die ich gehen sollte, beleuchten?

+2

Ihre i-Schleife endet zu früh. Der Zustand von i in Ihrem 'if ChgPos' (und dem Rest) ist unbestimmt. –

Antwort

6
  1. Sie mischen Komponenten und Kinder. Wenn Sie alle untergeordneten Elemente des Bedienfelds durchlaufen, verwenden Sie diesen Index nicht für die Eigenschaft Components, sondern für die Eigenschaft Children. (Ich nehme an, Ihr Code kompiliert und XE2 hat eine Children Eigenschaft, sonst denke ich, Sie meinen Controls und ControlCount).
  2. Wie LU RD bereits kommentiert, verwenden Sie die For-Schleife-Variable i außerhalb der For-Schleife. Ich bin sicher, du willst es drinnen haben. Sie sind auch durch den Compiler für diese gewarnt:

    FOR-Schleifenvariable ‚i‘ nach

    Schleife undefiniert sein kann

    immer sicherstellen, dass Sie haben null! Compilerfehler, Warnungen und Hinweise.

  3. Ich verstehe nicht Ihre Routine Logik für es lädt die Einstellungen, auch wenn Sie sie tatsächlich schreiben möchten. Ich denke, dass Sie nur die Einstellungen von der MemIniFile laden möchten, wenn ChgPos falsch ist.

keine Garantien gegeben, aber ich denke, die Routine sollte wie folgt aussehen (einschließlich ein paar Syntax Verbesserungen):

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; 

Obwohl ich die Standardwerte für die AnimIni.ReadInteger Funktion, PosX und PosY ernsthaft bezweifeln, welche nicht zugewiesen sind. Wenn kein Abschnitt in der INI-Datei gefunden wird, haben PosX und PosY willkürliche Werte. Sie sollten sie zu etwas initiieren, was sinnvoll ist.

+1

Ich denke, die Kinder-Eigenschaft muss FMX sein. –

+0

Genau das war es NGLN. "Kinder" ist in der Tat die FMX-Eigenschaft. Wie es war, gab es keine Warnung oder Hinweis über die Schleife (und nur über Variablen, die ich nicht aus anderen Verfahren verwendet hatte) Wegen der gut geschriebenen Erklärung und Code-Korrektur, muss ich diese Abstimmung geben Ihre Antwort, aber da mehrere Personen hilfreich waren, habe ich jede ihrer Antworten gewählt. –

3

Ihr Schleifenzähler und indizierte Eigenschaften stimmen nicht überein. ComponentCount und Components[] gehen zusammen.Und ChildrenCount und Children[] gehen zusammen. Sie möchten mit dem letzteren Paar arbeiten, da Sie in den Kindern der Kontrollen interessant sind. Die ComponentCount und Components[] Eigenschaften beziehen sich auf Eigentum, das ein anderes Konzept ist.

Außerdem endet Ihre Schleife, aber Sie verwenden weiterhin die Schleifenvariable nach der Schleifenvariablen. Das ist eindeutig falsch. Es sieht so aus, als müsste es innerhalb der Schleife und innerhalb des Scene.Children[i] is TSelection Tests sein.

Als Neben ChildrenCount ist grammatikalisch falsch neben ComponentCount und ControlCount. Diese Eigenschaft sollte ChildCount heißen.

Verwandte Themen