Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop (https://www.delphipraxis.net/161530-reihenfolge-von-zur-laufzeit-erstellten-komponenten-mit-align%3Daltop.html)

CCRDude 7. Jul 2011 14:47

Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
Ich erzeuge zuweil dynamisch TWinControls auf einer Form.

Beispiel (Ausschnitt):
Delphi-Quellcode:
for i := 1 to 10 do begin
   lbl := TLabel.Create(Self);
   lbl.Parent := sbParameters;
   lbl.Align := alTop;
   lbl.AlignWithMargins := true;
   lbl.Caption := IntToStr(i);
   FParameterEditors.Add(lbl);
end;
sbParameters ist dabei eine TScrollbox, FParameterEditors eine TComponentList.

In dieser Form habe ich sogar noch eine erwartete Reihenfolge. Nun füge ich aber TEdits hinzu:
Delphi-Quellcode:
for i := 1 to 10 do begin
   lbl := TLabel.Create(Self);
   lbl.Parent := sbParameters;
   lbl.Align := alTop;
   lbl.AlignWithMargins := true;
   lbl.Caption := IntToStr(i);
   lbl.Top := iParameter * 2;
   FParameterEditors.Add(lbl);
   edt := TEdit.Create(Self);
   edt.Parent := sbParameters;
   edt.Align := alTop;
   edt.AlignWithMargins := true;
   edt.ReadOnly := (p.Direction = bapdOut);
   edt.Top := iParameter * 2 + 1;
   edt.Text := 'HAllo Welt';
   FParameterEditors.Add(edt);
end;
In dieser Mischmasch-Form muss ich schon per obiger .Top-Zuweisung etwas "Ordnung" reinbringen, sonst habe ich 10 Labels übereinander, danach 10 Edits übereinander. Obwohl sie abwechselnd, nicht nacheinander, erstellt werden.

Füge ich nun noch zwischendurch ein paar TMemos ein, bekomme ich über eine einfache .Top-Zuweisung während der Erstellung die Original-Erstellungsreihenfolge nicht angezeigt. Da hilft mir nur noch ein:
Delphi-Quellcode:
   for iParameter := 0 to FParameterEditors.Count - 1 do begin
      if iParameter = 0 then begin
         TControl(FParameterEditors[iParameter]).Top := 0;
      end else begin
         TControl(FParameterEditors[iParameter]).Top := TControl(FParameterEditors[iParameter - 1]).Top + TControl(FParameterEditors[iParameter]).Height + 1;
      end;
   end;
Aber: da muss es doch etwas einfacheres geben? Was wäre denn die "Standard"-Methode zum dynamischen Einfügen von Controls, mit Align, sortiert? Gibt es da überhaupt etwas "vorgegebenes"? Oder etwas eleganteres?

shmia 7. Jul 2011 16:16

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
Das geht so nicht, wie du das vorhast.
Sobald mehr als zwei Controls auf einem Parentcontrol liegen und das Property Align benützen gibt es Probleme.
Du solltest die Position deiner Edits & Labels über Top und Left festlegen und Align auf alNone stehen lassen.

CCRDude 8. Jul 2011 09:26

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
Es geht schon so wie ich es vorhabe, siehe letztes Beispiel. Halt mit Align := alTop und dann Zuweisung von .Top nacheinander immer im passenden Abstand. Halte ich noch für weniger fehleranfällig als das von Dir vorgeschlagene (wobei ich zugegeben nach Deiner Methode auch problemlos Labels vor Edits packen könnte und diese nicht übereinander stapeln müsste, aber dieser Vorteil gehört nicht zur Fragestellung ;) ).

Und wenn es immer Probleme gäbe, gäbe es die ja auch mit zur Designzeit erstellen Controls, und damit wäre Align völlig hinfällig.

Da es dort aber offensichtlich eine Lösung gibt, wenn die VCL diese aus der .dfm (bzw. entsprechenden Resource im Binary natürlich) lädt, interessiert mich halt, wie daß dort gemacht wird, bzw. was dafür die sauberste Lösung wäre.

ChrisE 8. Jul 2011 10:45

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
Zitat:

Zitat von CCRDude (Beitrag 1110769)
... aber dieser Vorteil gehört nicht zur Fragestellung ;)...

In die selbe Richtung geht meine Anregung. Du könntest das Problem "halbieren" wenn du LabeledEdits verwendest ;-)

Aber zum Problem:

Ich habe da ähnliche Beobachtungen gemacht mit Komponenten die das selbe Align haben. Tatsächlich war es meist so ein durcheinander, dass ich es auch bevorzugt habe, die Komponenten von Hand zu platzieren und in der Parentkontrol auf das Ereignis OnResize zu reagieren und dann ggf. neu zu platzieren.

Das ist natürlich auch nicht die Antwort auf "Wie mache ich es mit mehreren Align:=alTop richtig" - es ist viel mehr ein Erfahrungsbericht, wie es vermeintlich besser läuft.

BTW: Es gibt auch die Möglichkeit über Align:=alCustom zu gehen und auf das Ereignis OnAlignPosition zu reagieren ;-)

Gruß, Chris

shmia 8. Jul 2011 11:04

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
Auf einem Panel (oder anderen Kontainer) kann man maximal zwei Controls stabil platzieren.
Das eine Control hat Align=alClient, während das andere Control Align=alTop,alLeft, alRight oder alBottom hat.

Sind es mehr als 2 Controls wird die Sache unstabil!
Wenn z.B. drei Controls auf alTop stehen, dann wollen ja alle ganz nach oben.
Tritt nun eine Störung ein (z.B. Resize des Kontainers), dann kann sich die Reihenfolge leicht ändern.
Bei noch mehr Controls wird die Sache zum Glücksspiel.

CCRDude 8. Jul 2011 12:35

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
@shmia: Inwiefern wird das denn instabil?

Wie gesagt, was zur Designzeit so erstellt wird, klappt doch?

Oft genug habe ich sowohl eine TStatusbar als auch ein TPanel unten. Oder eine TToolbarund ein TPanel oben im Fenster. Und hatte damit nie Probleme. Vielmillionenfach genutzt, ohen daß sich je ein Kunde über falsch plazierte UI-Elemente beschwert hätte.

Ich gehe sogar noch einen Schritt weiter - wenn Du recht hättest, gäbe es keinen TSplitter! Denn den setzte ich beispielweise mit Align := alLeft zwischen ein Panel mit Align = alClient und einem weiteren mit ebenfalls Align = alLeft. Anders als als zweite Komponente mit identischen Align macht TSplitter gar keinen Sinn (Ausnahme: schaltet man das Panel mit alLeft auch unsichtbar und dann wieder sichtbar, ist die Reihenfolge tatsächlich vertauscht, das weiß man und kann es beim Ändern des Visible beachten und ändern).

Möchtest Du behaupten, daß Borland/CodeGear/Embarcadero den TSplitter als unsupported unstable feature mitliefert? Wohl kaum ;)

Weitere Beispiele wären etwa TActionMainMenuBar plus TActionToolbar, die beide mit Align = alTop erzeugt werden und so zum Standard fast jedrn Anwendung mit TActionManager gehören dürften. Darf man, wenn man den TActionManager verwendet, nicht mehr Hauptmenü und Toolbar zusammen verwenden? Klingt für mich unglaubhaft.

Darüber hinaus stellst Du auch noch die Behauptung der maximal zwei Elemente auf. Ich kann Deine (meiner Meinung nach falsche) These ja vom Prinzip her verstehen, aber dann gäbe es doch immer noch mindestens 5 stabile Controls statt nur 2? alTop, alLeft, alRight und alBottom sind ja auch zusammen angewandt um ein Align = alClient immer noch "stabil".

Und ein Resize des Containers ist es doch gerade, was Align so wertvoll macht, nicht wo es Probleme verursacht?

@ChrisE: stimmt, LabeledEdits wäre ein halbiertes Problem, aber die mag ich irgendwie nicht ;)

Align = alCustom habe ich auch schon verwendet, wirklich nötig war es bei mir nur in Fällen, wo ich alTop, alLeft und alBottom zusammen verwendet habe, und das Control mit alLeft über die komplette Höhe gehen sollte. Da "versagt" dann auch Align selbst bzw. das ist dann nicht mehr seine Aufgabe).

Von Hand zu plazieren und auf OnResize zu reagieren, oder AlignWithMargins zuverwenden, oder auch die Anchors (beides macht OnResize eigentlich recht überflüssig in meiner Erfahrung), sind natürlich Möglichkeiten, klar :)

shmia 8. Jul 2011 13:04

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
Beim TSplitter handelt es sich in der Tat um eine Ausnahme; hier darf man auch 3 Controls auf einen Container packen.
Zitat:

Zitat von CCRDude (Beitrag 1110802)
...aber dann gäbe es doch immer noch mindestens 5 stabile Controls statt nur 2? alTop, alLeft, alRight und alBottom sind ja auch zusammen angewandt um ein Align = alClient immer noch "stabil".

Die Frage ist dann nur, welches Control darf die Ecken beanspruchen und welches Control wird aus der Ecke verdrängt?
Hier gilt dann das Prinzip "wer zuerst kommt mahlt zuerst".
Das bedeutet die Erstellungsreihenfolge der Controls hat direkten Einfluss auf das Layout.
Sollte ein Control, und sei es nur kurzzeitig, unsichtbar geschaltet werden und danach wieder sichtbar (Visible := True) dann hat es seine Position im Layout verloren
und die Anordnung hat sich geändert.
Das meine ich mit Unstabil.
Bei zwei Controls ist die Erstellungsreihenfolge unerheblich; die Kombination aus (alTop|alLeft|alRight|alBottom) zusammen mit alClient ist immer stabil.

CCRDude 8. Jul 2011 13:10

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
Und TActionMainMenuBar plus TActionToolbar sind dann die nächste Ausnahme, und dann gibt es noch diese Ausnahme, und jene...?

Die Ecken hängen bei Align nicht von der Erstellungsreihenfolge ab, da gibt es afaik eine definierte Reihenfolge, ich glaube alTop und alBottom haben Vorrang vor alLeft und alRight.

Natürlich bestehen die Problematiken, die Du erwähnt hast: unsichtbarschalten etwa.

Aber: die existieren nur, wenn man etwa Visible ändert. Das macht die VCL nicht von alleine. Und ob das unstabil oder nicht ist, hängt also davon ab, ob man mit eigenem Code etwas berücksichtigt, was eigener Code verursacht. Das ist für mich weit an der Definitiv von "unstabil" vorbei!

Egal, den Kern hast Du ja erwähnt - die Erstellungsreihenfolge. Danach fragte ich ja - wie ist das VCL-intern beim Formerstellen zur Laufzeit geregelt (die ist mMn sehr stabil und reproduzierbar) und was ist daran anders als an meiner dynamischen Erzeugung?

SirThornberry 8. Jul 2011 17:36

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
Wenn man zur Designzeit etwas aufs Form packt wird doch auch "Top" mit abgespeichert.
Dadurch klappt das auch mit der Positionierung.
Die Erstellungsreihenfolge ist dabei egal denn das Align wird nicht ausgeführt wenn ein neues Control hinzu kommt sondern erst wenn Handles angefordert werden etc.
Das kann man wunderbar beobachten wenn man ein Control dynamisch erzeugt, den Align-Wert setzt und direkt danach Top/Left/Width/Height ausliest. Diese Werte ändern sich frühestens wenn das nächste mal Messages abgearbeitet werden oder eben durch einen manuellen Aufruf von ReAlign

stahli 9. Jul 2011 10:02

AW: Reihenfolge von zur Laufzeit erstellten Komponenten mit Align=alTop
 
M.E. wurde das Verhalten "irgendwann einmal" in Delphi geändert (in diesem Punkt verschlechtert).
Ich denke, früher war es so, dass beim Align die "ursprüngliche" Position den Komponenten (Top, Left) zu Ausrichtung herangezogen wurden.
Heute wird die "aktuelle" Position verwendet. Wenn man nun ein Control unsichtbar und dann wieder sichtbar macht, verschieben sich die Reihenfolgen, da sich die anderen Controls zischenzeitlich verschoben wurden.
Bei solchen Anforderungen setze ich die Höhe des Auszublendenden Controls inzwischen manchmal auf 0 und dann wieder zurück.

Ich meine früher, war das Verhalten der VCL in diesem Punkt vorhersehbarer und besser.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:48 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz