Difference between revisions of "Anchor Sides/ru"

From Lazarus wiki
Jump to navigationJump to search
m
m (Fixed syntax highlighting)
 
(One intermediate revision by one other user not shown)
Line 16: Line 16:
 
== В коде ==
 
== В коде ==
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Edit1.AnchorSide[akLeft].Side := asrRight;
 
Edit1.AnchorSide[akLeft].Side := asrRight;
 
Edit1.AnchorSide[akLeft].Control := Label1;
 
Edit1.AnchorSide[akLeft].Control := Label1;
Line 24: Line 24:
 
Вы можете задать расстояние с помощью свойств BorderSpacing:
 
Вы можете задать расстояние с помощью свойств BorderSpacing:
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Edit1.BorderSpacing.Left := 10;
 
Edit1.BorderSpacing.Left := 10;
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 30: Line 30:
 
То-же самое может быть сделано с помощью метода:
 
То-же самое может быть сделано с помощью метода:
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Edit1.AnchorToNeighbour(akLeft, 10, Label1);
 
Edit1.AnchorToNeighbour(akLeft, 10, Label1);
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 55: Line 55:
 
</pre>
 
</pre>
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Edit1.AnchorSide[akTop].Side := asrTop;
 
Edit1.AnchorSide[akTop].Side := asrTop;
 
Edit1.AnchorSide[akTop].Control := Label1;
 
Edit1.AnchorSide[akTop].Control := Label1;
Line 63: Line 63:
 
То-же самое может быть сделано с помощью метода:
 
То-же самое может быть сделано с помощью метода:
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Edit1.AnchorParallel(akTop,0,Label1);
 
Edit1.AnchorParallel(akTop,0,Label1);
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 78: Line 78:
 
</pre>
 
</pre>
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Edit1.AnchorSide[akTop].Side := asrCenter;
 
Edit1.AnchorSide[akTop].Side := asrCenter;
 
Edit1.AnchorSide[akTop].Control := Label1;
 
Edit1.AnchorSide[akTop].Control := Label1;
Line 86: Line 86:
 
То-же самое может быть сделано с помощью метода:
 
То-же самое может быть сделано с помощью метода:
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Edit1.AnchorVerticalCenterTo(Label1);
 
Edit1.AnchorVerticalCenterTo(Label1);
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 94: Line 94:
 
= Новое свойство =
 
= Новое свойство =
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
property AnchorSide[Kind: TAnchorKind]: TAnchorSide read GetAnchorSide;
 
property AnchorSide[Kind: TAnchorKind]: TAnchorSide read GetAnchorSide;
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 103: Line 103:
 
= Новые методы для лёгкого конфигурирования общего расположения =
 
= Новые методы для лёгкого конфигурирования общего расположения =
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
procedure AnchorToNeighbour(Side: TAnchorKind; Space: integer;
 
procedure AnchorToNeighbour(Side: TAnchorKind; Space: integer;
 
                             Sibling: TControl);
 
                             Sibling: TControl);
Line 137: Line 137:
 
Есть одно исключение из этого правила. Если '''Parent.AutoSize''' установлено в True, то LCL будет автоматически разрывать циклы на autosize и писать предупреждение через '''debugln''' (windows: --debug-log.txt, linux, et al: stdout). Которая из привязок будет нарушена, зависит от порядка элементов управления и сторон. Таким образом, временные циклы остаются разрешёнными при AutoSize=true, если вы заключите изменение в:  
 
Есть одно исключение из этого правила. Если '''Parent.AutoSize''' установлено в True, то LCL будет автоматически разрывать циклы на autosize и писать предупреждение через '''debugln''' (windows: --debug-log.txt, linux, et al: stdout). Которая из привязок будет нарушена, зависит от порядка элементов управления и сторон. Таким образом, временные циклы остаются разрешёнными при AutoSize=true, если вы заключите изменение в:  
  
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
Parent.DisableAutosizing;
 
Parent.DisableAutosizing;
 
try
 
try
Line 151: Line 151:
  
 
*[[Autosize / Layout]]
 
*[[Autosize / Layout]]
 +
*[[Example: Anchors. How to reliably align dynamically created controls under changing visibility]]

Latest revision as of 07:15, 9 February 2020

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

Есть несколько новых свойств и методов для автоматического расположения элементов управления. Теперь вы можете настроить элементы управления для поддержания определённого расстояния до других элементов управления или центрирования относительно других элементов управления. Смотрите пример ниже.

Каждая из четырёх сторон элемента управления (Left, Top, Right, Bottom) теперь может быть прикреплена/привязана к стороне другого элемента управления. Например, теперь вы можете привязать левую сторону TEdit к правой стороне TLabel. Каждый раз, когда Label перемещается или меняет размер, левая сторона Edit будет следовать за ней, что обычно приводит к перемещению Edit параллельно Label.

Пример 1

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

В коде

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

Вы можете задать расстояние с помощью свойств BorderSpacing:

Edit1.BorderSpacing.Left := 10;

То-же самое может быть сделано с помощью метода:

Edit1.AnchorToNeighbour(akLeft, 10, Label1);

Примечания

Edit1.Left будет следовать за Label1.Left+Label1.Width, но не наоборот. Это означает, что перемещение Label1 будет вызывать перемещение Edit1. Но перемещение Edit1 будет отменяться LCL. Если вы также привяжете правую сторону Label1 к левой стороне Edit1, вы создадите кольцо и в сочетании с некоторыми другими свойствами авторазмера это приведёт к циклу. Это игнорируется LCL или автоматически исправляется, когда Parent.AutoSize установлено в True.

С помощью редактора якорей

Редактор якорей - плавающее окно, доступное через меню View / Anchor Editor или через кнопку в свойстве Anchors в инспекторе объектов.

Anchoreditor.png

Пример 2

Вы можете привязать верхний край Edit для следования за верхним краем Label:

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

То-же самое может быть сделано с помощью метода:

Edit1.AnchorParallel(akTop,0,Label1);

Пример 3

Вертикальное центрирование Edit относительно Label:

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

То-же самое может быть сделано с помощью метода:

Edit1.AnchorVerticalCenterTo(Label1);

Очевидно, что привязка нижнего края Edit1 не имеет смысла при центрировании.

Новое свойство

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

Это свойство не опубликовано в инспекторе объектов. Вы можете редактировать его в дизайнере с помощью редактора якорей
(меню View -> View anchor editor или щелчок на кнопке свойства Anchors).

Новые методы для лёгкого конфигурирования общего расположения

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 работает также с Parent. Тогда центрирование будет происходить по клиентской области, это означает, что центр элемента управления будет в ClientHeight div 2.

Привязка по центру пока не полностью поддерживается при вычислении размера родителя. Например, когда вы помещаете привязанную по центру метку в Groupbox1 и устанавливаете Groupbox1.AutoSize в True, то высота Groupbox1 будет уменьшаться, не оставляя места для метки. Решение состоит в центрировании по элементу, который не центрирован. Например, центрируйте Label1 по ComboBox и используйте для ComboBox якоря по умолчанию (Anchors=[akLeft,akTop]).

Привязка к невидимым элементам управления

Начиная с 0.9.25 rev 12800 привязка к невидимым элементам управления была изменена, чтобы работать более интуитивно. Например, ниже элементы управления A, B, C привязаны (C.Left к B.Right и B.Left к A.Right):

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

Если B скрыт (Visible:=false), то C.Left будет пропускать B и использовать правый край A, в результате получим следующее:

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

Циклические ссылки

Вы можете создать циклические ссылки, привязав два края друг к другу, что создаёт невозможную привязку. LCL замечает это, но не генерирует исключения, поскольку этот цикл может быть времнным. Например, ряд кнопок: Button1 слева от Button2, Button2 слева от Button3. Теперь меняем порядок на следующий: Button3, Button1, Button2. Если перепривязка начата с Button3, временно создаётся цикл, который исправляется по завершению переупорядочивания. LCL обнаруживает цикл и не перемещает Button. Циклы - не единственная аномалия.

Есть одно исключение из этого правила. Если Parent.AutoSize установлено в True, то LCL будет автоматически разрывать циклы на autosize и писать предупреждение через debugln (windows: --debug-log.txt, linux, et al: stdout). Которая из привязок будет нарушена, зависит от порядка элементов управления и сторон. Таким образом, временные циклы остаются разрешёнными при AutoSize=true, если вы заключите изменение в:

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

Алгоритм AutoSize не только разрушает циклы, но также исправляет несоответствия Align/AnchorSide.

См. также