Difference between revisions of "Anchor Sides/de"

From Free Pascal wiki
Jump to navigationJump to search
 
m (Fixed syntax highlighting)
 
(26 intermediate revisions by 8 users not shown)
Line 1: Line 1:
There are some new properties and methods for automatic layout of
+
{{Anchor Sides}}
controls.
 
You can now setup controls to keep a certain distance to other controls,
 
or center relative to other controls. See below for examples.
 
  
Each of the four sides of a control (Left, Top, Right, Bottom) can now
+
Es gibt einige neue Eigenschaften und Methoden für das automatische Layout von Steuerelementen.
be anchored/bound to a side of another control. For example you can now
+
Sie können jetzt Bedienelemente so einstellen, dass sie einen bestimmten Abstand zu anderen Bedienelementen einhalten,
anchor the left side of TEdit to the right side of a TLabel. Everytime
+
oder relativ zu anderen Bedienelementen zentrieren. Siehe unten für Beispiele.
the Label is moved or resized the Edit's left side will follow, which
+
 
normally results in moving the Edit parallel to the Label.
+
Jede der vier Seiten eines Bedienelements (Left, Top, Right, Bottom) kann jetzt verankert/angebunden werden an der Seite eines anderen Bedienelements. Zum Beispiel können Sie jetzt die linke Seite eines TEdit an der rechten Seite eines TLabel verankern. Jedes Mal, wenn das Label bewegt wird oder in der Größe angepasst wird, dann wird die linke Seite des Edit folgen, was normalerweise zu einer Bewegung des Edit parallel zum Label führt.
  
 
=Beispiel 1=
 
=Beispiel 1=
Line 15: Line 12:
 
  +--------+ |      |
 
  +--------+ |      |
 
             +-------+
 
             +-------+
==In code==
+
==Im Code==
Edit1.AnchorSide[akLeft].Side:=asrRight;
+
 
Edit1.AnchorSide[akLeft].Control:=Label1;
+
<syntaxhighlight lang=pascal>Edit1.AnchorSide[akLeft].Side:=asrRight;
Edit1.Anchors:=Edit1.Anchors+[akLeft];
+
Edit1.AnchorSide[akLeft].Control:=Label1;
You can define the distance with the BorderSpacing properties:
+
Edit1.Anchors:=Edit1.Anchors+[akLeft];</syntaxhighlight>
Edit1.BorderSpacing.Left:=10;
+
 
The same can be done with the method:
+
Sie können den Abstand mit den Eigenschaften von BorderSpacing definieren:
Edit1.AnchorToNeighbour(akLeft,10,Label1);
+
<syntaxhighlight lang=pascal>Edit1.BorderSpacing.Left:=10;</syntaxhighlight>
==Notes==
+
Das selbe kann mit der Methode gemacht werden:
The Edit1.Left will follow Label1.Left+Label1.Width, not the other way
+
<syntaxhighlight lang=pascal>Edit1.AnchorToNeighbour(akLeft,10,Label1);</syntaxhighlight>
around. That means, moving Label1 will move Edit1. But moving Edit1 will
+
 
be undone by the LCL.
+
==Anmerkungen==
If you also anchor the right side of Label1 to the left side of Edit1,
+
Edit1.Left wird Label1.Left+Label1.Width folgen, nicht umgekehrt. Das bedeutet, dass eine Bewegung von Label1 auch Edit1 bewegen wird. Aber eine Bewegung von Edit1 wird von der LCL annulliert.
you created a circle, and this can result together with some other
+
Wenn Sie auch die rechte Seite von Label1 an der linken Seite von Edit1 verankern,
autosize properties in an infinite loop. Detection of circles is not yet
+
dann erzeugen sie einen Kreis. Dies kann zusammen mit einigen anderen Autosize-Eigenschaften eine Endlosschleife verursachen. Ist Parent.AutoSize auf true gesetzt, wird dies von der LCL ignoriert oder automatisch repariert.
implemented.
+
 
 +
==Mittels des Ankereditors==
 +
 
 +
Der Ankereditor ist ein schwebendes Fenster, den Sie erreichen über das Menü '''Ansicht / Ankereditor anzeigen''' oder über die Schaltfläche in der Eigenschaft '''Anchors''' des Objektinspektors.
 +
 
 +
[[Image:Anchor_Editor_de.png]]
  
 
=Beispiel 2=
 
=Beispiel 2=
  
You can anchor the Edit's top side to follow the Label's top side:
+
Sie können die obere Seite von Edit1 so verankern, dass sie der oberen Seite von Label1 folgt:
 
<pre>
 
<pre>
 
+--------+ +-------+
 
+--------+ +-------+
Line 41: Line 43:
 
           +-------+
 
           +-------+
 
</pre>
 
</pre>
<pre>
+
<syntaxhighlight lang=pascal>Edit1.AnchorSide[akTop].Side:=asrTop;
Edit1.AnchorSide[akTop].Side:=asrTop;
 
 
Edit1.AnchorSide[akTop].Control:=Label1;
 
Edit1.AnchorSide[akTop].Control:=Label1;
Edit1.Anchors:=Edit1.Anchors+[akTop];
+
Edit1.Anchors:=Edit1.Anchors+[akTop];</syntaxhighlight>
</pre>
+
Das selbe kann mit der Methode gemacht werden:
The same can be done with the method:
+
<syntaxhighlight lang=pascal>Edit1.AnchorParallel(akTop,0,Label1);</syntaxhighlight>
<pre>Edit1.AnchorParallel(akTop,0,Label1);</pre>
 
  
 
=Beispiel 3=
 
=Beispiel 3=
  
Centering a Label vertically to an Edit:
+
Vertikale Zentrierung von Label1 an Edit1:
 
<pre>
 
<pre>
 
           +-------+
 
           +-------+
Line 59: Line 59:
 
           +-------+
 
           +-------+
 
</pre>
 
</pre>
<pre>
+
<syntaxhighlight lang=pascal>Edit1.AnchorSide[akTop].Side:=asrCenter;
Edit1.AnchorSide[akTop].Side:=asrCenter;
 
 
Edit1.AnchorSide[akTop].Control:=Label1;
 
Edit1.AnchorSide[akTop].Control:=Label1;
Edit1.Anchors:=Edit1.Anchors+[akTop]-[akBottom];
+
Edit1.Anchors:=Edit1.Anchors+[akTop]-[akBottom];</syntaxhighlight>
</pre>
+
Das selbe kann mit der Methode gemacht werden:
The same can be done with the method:
+
<syntaxhighlight lang=pascal>Edit1.AnchorVerticalCenterTo(Label1);</syntaxhighlight>
<pre>Edit1.AnchorVerticalCenterTo(Label1);</pre>
 
  
Obviously anchoring the bottom side of Edit1 does not make sense when
+
Offensichtlich ist die Verankerung der unteren Seite von Edit1 bei einer Zentrierung nicht sinnvoll.
centering.
 
  
=New property=
+
=Neue Eigenschaft=
<pre>property AnchorSide[Kind: TAnchorKind]: TAnchorSide read GetAnchorSide;</pre>
+
<syntaxhighlight lang=pascal>property AnchorSide[Kind: TAnchorKind]: TAnchorSide read GetAnchorSide;</syntaxhighlight>
This is not published in the object inspector. You can edit it in the
+
Dies wird nicht im Objektinspektor veröffentlicht. Sie können sie zur Entwicklungszeit mit dem Ankereditor bearbeiten (Menü: Ansicht -> Ankereditor anzeigen, oder
designer via the anchor editor (Menu: View -> View anchor editor, or
+
auf den Button der 'Anchors' Eigenschaft klicken).
click on button of 'Anchors' property).
 
  
=New methods to easily configure common layouts=
+
=Neue Methoden zur einfachen Konfiguration eines gebräuchlichen Layouts=
<pre>
+
<syntaxhighlight lang=pascal>procedure AnchorToNeighbour(Side: TAnchorKind; Space: integer;
procedure AnchorToNeighbour(Side: TAnchorKind; Space: integer;
 
 
                             Sibling: TControl);
 
                             Sibling: TControl);
 
procedure AnchorParallel(Side: TAnchorKind; Space: integer;
 
procedure AnchorParallel(Side: TAnchorKind; Space: integer;
Line 84: Line 79:
 
procedure AnchorHorizontalCenterTo(Sibling: TControl);
 
procedure AnchorHorizontalCenterTo(Sibling: TControl);
 
procedure AnchorVerticalCenterTo(Sibling: TControl);
 
procedure AnchorVerticalCenterTo(Sibling: TControl);
</pre>
+
procedure AnchorAsAlign(TheAlign: TAlign; Space: Integer);</syntaxhighlight>
 +
 
 +
AnchorVerticalCenterTo arbetet auch mit Eltern. Dann wird auf den Client-Bereich zentriert, das bedeutet die Mitte des Steuerelements ist bei ''ClientHeight div 2''.
 +
 
 +
Das zentrierte Verankern ist noch nicht vollständig unterstützt für die Berechnung der Größe der Eltern. Wenn Sie beispielsweise ein Label in einer Groupbox1 zentriert verankern und Groupbox1.AutoSize auf true setzen, dann schrumpft die Höhe der Groupbox1 und läßt keinen Platz für das Label. Die Lösung besteht darin, auf ein Steuerelement zu zentrieren, das selbst nicht zentriert ist. Zum Beispiel zentriere ein Label1 auf eine ComboBox und nimm für die ComboBox die vorgegebenen Anker (Anchors=[akLeft,akTop]).
 +
 
 +
=Verankern an unsichtbaren Kontrollelementen=
 +
 
 +
Ab Version 0.9.25 rev 12800 wurde das Verankern an unsichtbaren Kontrollelemente geändert, damit es intuitiver arbeitet. Beispiel: Die Kontrollelemente A, B und C sind wie folgt verankert (C.Left an B.Right und B.Left an A.Right):
 +
 
 +
  +---+ +---+ +---+
 +
  | A | | B | | C |
 +
  +---+ +---+ +---+
 +
 
 +
Ist B unsichtbar (Visible:=false), wird C.Left B überspringen und sich an der rechten Seite von A verankern, womit das Ganze dann so aussieht:
 +
 
 +
  +---+ +---+
 +
  | A | | C |
 +
  +---+ +---+
 +
 
 +
=Zirkuläre Bezüge=
 +
 
 +
Sie erhalten einen Zirkularbezug, wenn Sie zwei Seiten an der jeweils anderen verankern. Dies liefert eine unmögliche Verankerung. Die LCL bemerkt das, löst aber keine Exception aus, weil es sich um einen temporären Kreis handeln könnte. Zum Beispiel: Eine Reihe von Schaltflächen. Button1 ist links von Button2, Button2 ist links von Button3. Jetzt verändern wir die Reihenfolge zu: Button3, Button1, Button2. Wenn die Verankerung mit Button3 startet, entsteht ein temporärer Kreis der aufgelöst wird, wenn das Umordnen abgeschlossen ist. Die LCL entdeckt Kreise und wird den Button nicht verschieben. Kreise sind nicht die einzige Anomalie.
 +
 
 +
Es gibt eine Ausnahme zu dieser Regel. Wenn Parent.AutoSize wahr ist, dann bricht die LCL beim Autosize Kreise automatisch auf und schreibt eine Warnung über debugln (Windows: --debug-log.txt, Linux, et al: stdout). Welcher Anker aufgebrochen wird hängt von der Reihenfolge der Steuerelemente und der Seiten ab. Deshalb sind temporäre Kreise erlaubt mit AutoSize:=true wenn Sie die Änderungen einschließen in
 +
 
 +
<syntaxhighlight lang=pascal>
 +
Parent.DisableAutosizing;
 +
try
 +
  // change anchors, aligns, bounds...
 +
finally
 +
  Parent.EnableAutosizing;
 +
end;
 +
</syntaxhighlight>
 +
 
 +
Der AutoSize-Algorithmus bricht nicht nur Kreisbezüge auf, sondern beseitigt auch Inkonsistenzen mit Align/AnchorSide.
 +
 
 +
Eventuell wäre es günstig, im Designer Hinweise darauf einzufügen oder ein Werkzeug zum Auflisten der Kreisbezüge und Inkonsistenzen.
 +
 
 +
=Siehe auch=
 +
 
 +
* [[Autosize / Layout]]
 +
* [[LCL AutoSizing]]
 +
* [[Example: Anchors. How to reliably align dynamically created controls under changing visibility]]
 +
<br>
 +
<br>
 +
 
 +
[[Category:Lazarus/de]]

Latest revision as of 06:38, 6 February 2020

Deutsch (de) English (en) français (fr) 日本語 (ja) русский (ru)

Es gibt einige neue Eigenschaften und Methoden für das automatische Layout von Steuerelementen. Sie können jetzt Bedienelemente so einstellen, dass sie einen bestimmten Abstand zu anderen Bedienelementen einhalten, oder relativ zu anderen Bedienelementen zentrieren. Siehe unten für Beispiele.

Jede der vier Seiten eines Bedienelements (Left, Top, Right, Bottom) kann jetzt verankert/angebunden werden an der Seite eines anderen Bedienelements. Zum Beispiel können Sie jetzt die linke Seite eines TEdit an der rechten Seite eines TLabel verankern. Jedes Mal, wenn das Label bewegt wird oder in der Größe angepasst wird, dann wird die linke Seite des Edit folgen, was normalerweise zu einer Bewegung des Edit parallel zum Label führt.

Beispiel 1

+--------+ +-------+
| Label1 | | Edit1 |
+--------+ |       |
           +-------+

Im Code

Edit1.AnchorSide[akLeft].Side:=asrRight;
Edit1.AnchorSide[akLeft].Control:=Label1;
Edit1.Anchors:=Edit1.Anchors+[akLeft];

Sie können den Abstand mit den Eigenschaften von BorderSpacing definieren:

Edit1.BorderSpacing.Left:=10;

Das selbe kann mit der Methode gemacht werden:

Edit1.AnchorToNeighbour(akLeft,10,Label1);

Anmerkungen

Edit1.Left wird Label1.Left+Label1.Width folgen, nicht umgekehrt. Das bedeutet, dass eine Bewegung von Label1 auch Edit1 bewegen wird. Aber eine Bewegung von Edit1 wird von der LCL annulliert. Wenn Sie auch die rechte Seite von Label1 an der linken Seite von Edit1 verankern, dann erzeugen sie einen Kreis. Dies kann zusammen mit einigen anderen Autosize-Eigenschaften eine Endlosschleife verursachen. Ist Parent.AutoSize auf true gesetzt, wird dies von der LCL ignoriert oder automatisch repariert.

Mittels des Ankereditors

Der Ankereditor ist ein schwebendes Fenster, den Sie erreichen über das Menü Ansicht / Ankereditor anzeigen oder über die Schaltfläche in der Eigenschaft Anchors des Objektinspektors.

Anchor Editor de.png

Beispiel 2

Sie können die obere Seite von Edit1 so verankern, dass sie der oberen Seite von Label1 folgt:

+--------+ +-------+
| Label1 | | Edit1 |
+--------+ |       |
           +-------+
Edit1.AnchorSide[akTop].Side:=asrTop;
Edit1.AnchorSide[akTop].Control:=Label1;
Edit1.Anchors:=Edit1.Anchors+[akTop];

Das selbe kann mit der Methode gemacht werden:

Edit1.AnchorParallel(akTop,0,Label1);

Beispiel 3

Vertikale Zentrierung von Label1 an Edit1:

           +-------+
+--------+ |       |
| Label1 | | Edit1 |
+--------+ |       |
           +-------+
Edit1.AnchorSide[akTop].Side:=asrCenter;
Edit1.AnchorSide[akTop].Control:=Label1;
Edit1.Anchors:=Edit1.Anchors+[akTop]-[akBottom];

Das selbe kann mit der Methode gemacht werden:

Edit1.AnchorVerticalCenterTo(Label1);

Offensichtlich ist die Verankerung der unteren Seite von Edit1 bei einer Zentrierung nicht sinnvoll.

Neue Eigenschaft

property AnchorSide[Kind: TAnchorKind]: TAnchorSide read GetAnchorSide;

Dies wird nicht im Objektinspektor veröffentlicht. Sie können sie zur Entwicklungszeit mit dem Ankereditor bearbeiten (Menü: Ansicht -> Ankereditor anzeigen, oder auf den Button der 'Anchors' Eigenschaft klicken).

Neue Methoden zur einfachen Konfiguration eines gebräuchlichen Layouts

procedure AnchorToNeighbour(Side: TAnchorKind; Space: integer;
                            Sibling: TControl);
procedure AnchorParallel(Side: TAnchorKind; Space: integer;
                         Sibling: TControl);
procedure AnchorHorizontalCenterTo(Sibling: TControl);
procedure AnchorVerticalCenterTo(Sibling: TControl);
procedure AnchorAsAlign(TheAlign: TAlign; Space: Integer);

AnchorVerticalCenterTo arbetet auch mit Eltern. Dann wird auf den Client-Bereich zentriert, das bedeutet die Mitte des Steuerelements ist bei ClientHeight div 2.

Das zentrierte Verankern ist noch nicht vollständig unterstützt für die Berechnung der Größe der Eltern. Wenn Sie beispielsweise ein Label in einer Groupbox1 zentriert verankern und Groupbox1.AutoSize auf true setzen, dann schrumpft die Höhe der Groupbox1 und läßt keinen Platz für das Label. Die Lösung besteht darin, auf ein Steuerelement zu zentrieren, das selbst nicht zentriert ist. Zum Beispiel zentriere ein Label1 auf eine ComboBox und nimm für die ComboBox die vorgegebenen Anker (Anchors=[akLeft,akTop]).

Verankern an unsichtbaren Kontrollelementen

Ab Version 0.9.25 rev 12800 wurde das Verankern an unsichtbaren Kontrollelemente geändert, damit es intuitiver arbeitet. Beispiel: Die Kontrollelemente A, B und C sind wie folgt verankert (C.Left an B.Right und B.Left an A.Right):

 +---+ +---+ +---+
 | A | | B | | C |
 +---+ +---+ +---+

Ist B unsichtbar (Visible:=false), wird C.Left B überspringen und sich an der rechten Seite von A verankern, womit das Ganze dann so aussieht:

 +---+ +---+
 | A | | C |
 +---+ +---+

Zirkuläre Bezüge

Sie erhalten einen Zirkularbezug, wenn Sie zwei Seiten an der jeweils anderen verankern. Dies liefert eine unmögliche Verankerung. Die LCL bemerkt das, löst aber keine Exception aus, weil es sich um einen temporären Kreis handeln könnte. Zum Beispiel: Eine Reihe von Schaltflächen. Button1 ist links von Button2, Button2 ist links von Button3. Jetzt verändern wir die Reihenfolge zu: Button3, Button1, Button2. Wenn die Verankerung mit Button3 startet, entsteht ein temporärer Kreis der aufgelöst wird, wenn das Umordnen abgeschlossen ist. Die LCL entdeckt Kreise und wird den Button nicht verschieben. Kreise sind nicht die einzige Anomalie.

Es gibt eine Ausnahme zu dieser Regel. Wenn Parent.AutoSize wahr ist, dann bricht die LCL beim Autosize Kreise automatisch auf und schreibt eine Warnung über debugln (Windows: --debug-log.txt, Linux, et al: stdout). Welcher Anker aufgebrochen wird hängt von der Reihenfolge der Steuerelemente und der Seiten ab. Deshalb sind temporäre Kreise erlaubt mit AutoSize:=true wenn Sie die Änderungen einschließen in

Parent.DisableAutosizing;
try
  // change anchors, aligns, bounds...
finally
  Parent.EnableAutosizing;
end;

Der AutoSize-Algorithmus bricht nicht nur Kreisbezüge auf, sondern beseitigt auch Inkonsistenzen mit Align/AnchorSide.

Eventuell wäre es günstig, im Designer Hinweise darauf einzufügen oder ein Werkzeug zum Auflisten der Kreisbezüge und Inkonsistenzen.

Siehe auch