[SOLVED] How to reliably align dynamically created buttons lazarus / 31-LCL ---------------------------------------------------------------------- eny · 2016-01-26 18:00 5 buttons are created dynamically and right aligned on a panel (see pic 1 buttons 5-4-3-2-1).Then all are hidden and made visible. Now the order of the buttons is reversed  (see pic 2 buttons 1-2-3-4-5)Then all are hidden again and made visible again. Now the order is a complete mess  (see pic 3 buttons 3-2-4-1-5)How to avoid this and keep the order consistent without anchoring? (not all buttons are visible necessarily at the same time) (laz 1.4.4) Short demo program to reproduce (one form with 2 buttons and 2 panels): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit ufrmMain; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls; type   { TfrmMain }   TfrmMain = class(TForm)    Button1: TButton;    Button2: TButton;    Panel1: TPanel;    Panel2: TPanel;   procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);   private    { private declarations }  Buttons: array[1..5] of TButton;  public    { public declarations }  end; var  frmMain: TfrmMain; implementation {$R *.lfm} { TfrmMain } procedure TfrmMain.Button1Click(Sender: TObject);var i: integer;begin  // Dynamically create 5 buttons  for i := 1 to 5 do  begin    Buttons[i] := TButton.Create(Panel2);    Buttons[i].Parent := Panel2;    Buttons[i].Caption := format('Button %d',[i]);    Buttons[i].BorderSpacing.Around := 4;    Buttons[i].Align := alRight;  end;end; procedure TfrmMain.Button2Click(Sender: TObject);var i: integer;begin  // Hide the buttons first  for i := 1 to 5 do    Buttons[i].Visible := false;  ShowMessage('Buttons are gone...');   // Show them again  for i := 1 to 5 do    Buttons[i].Visible := true;end;end. ---------------------------------------------------------------------- wp · 2016-01-26 18:38 Before showing each button set its Left to 0. Since the buttons are right-aligned the LCL will move the button to the left of the already shown buttons. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmMain.Button2Click(Sender: TObject);var i: integer;begin    // Hide the buttons first    for i := 1 to 5 do    Buttons[i].Visible := false;    ShowMessage('Buttons are gone...');      // Show them again  for i := 1 to 5 do begin    Buttons[i].Left := 0;    Buttons[i].Visible := true;  end;end; ---------------------------------------------------------------------- eny · 2016-01-26 18:58 Great stuff! This seems to work  The only problem is that from an architectural point of view, I don't have access to the button properties: I use an action list and enable/disable and hide/show the 'actions' and do not/can not manipulate the controls directly. So now I have to 'break' the architecture and 'pollute' the code with resetting the left property of the associated buttons. Nevertheless, I'm happy with the workaround because at least it is possible to align the controls as required. ---------------------------------------------------------------------- wp · 2016-01-26 19:44 What about using TAction.ActionComponent to get the control which fired the action? http://docs.getlazarus.org/rtl/classes/tbasicaction. actioncomponent.html ---------------------------------------------------------------------- eny · 2016-01-26 20:00 Quote from: wp on January 26, 2016, 08:44:17 pmWhat about using TAction.ActionComponent to get the control which fired the action? htt p://docs.getlazarus.org/rtl/classes/tbasicaction.actioncomponent.html In my case that does not work because the problem lies in hiding/showing the buttons. Not so much in capturing the action event (that works as advertised). The buttons (or better: functions) are context-sensitive and enabled when appropriate. So they are hidden until something in the context changes. Then they are enabled where appropriate by setting the corresponding action to enabled/visible. That's why I was hoping that they would be aligned based on either the creation order or order in which they were made visible. ---------------------------------------------------------------------- FTurtle · 2016-01-26 20:12 Use anchors. Read here: http://wiki.lazarus.freepascal.org/Anchor_Sides Working example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,  Buttons, StdCtrls; type   { TForm1 }   TForm1 = class(TForm)    CheckGroup1: TCheckGroup;    Panel1: TPanel;    procedure CheckGroup1ItemClick(Sender: TObject; Index: integer);    procedure FormCreate(Sender: TObject);  private    FButtons: array of TButton;  public    { public declarations }  end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject);var  i: Integer;begin  if CheckGroup1.Items.Count = 0 then    Exit;  SetLength(FButtons, CheckGroup1.Items.Count);   for i:=Low(FButtons) to High(FButtons) do  begin    FButtons[i] := TButton.Create(Self);    with FButtons[i] do  begin      Parent := Panel1;      Caption := IntToStr(i+1);      CheckGroup1.Checked[i] := True;      Anchors := [akTop, akBottom, akRight];       AnchorSide[akTop].Control := Parent;      AnchorSide[akTop].Side := asrTop;       AnchorSide[akBottom].Control := Parent;      AnchorSide[akBottom].Side := asrBottom;       if i=0 then      begin        AnchorSide[akRight].Control := Parent;        AnchorSide[akRight].Side := asrRight;      end      else      begin      AnchorSide[akRight].Control := FButtons[i-1];        AnchorSide[akRight].Side := asrLeft;      end;    end;  end;end; procedure TForm1.CheckGroup1ItemClick(Sender: TObject; Index: integer);begin  FButtons[Index].Visible := (Sender as TCheckGroup).Checked[Index];end; end. ---------------------------------------------------------------------- eny · 2016-01-26 21:15 Quote from: FTurtle on January 26, 2016, 09:12:53 pmUse anchors. Read here: http://wiki.lazarus.freepascal.org/Anchor_Sides Working example:...As much as I hate using anchors (the documentation is way too cryptic), this example actually seems to work ánd having the benefit that I can hide and show actions based on the context. Great stuff! (Will test and report back.) <> Tested and works like a charm! wp/FTurtle: thx for the suggestions.