Delphi: How to programmatically adjust visual ordering of components with align = alTop
Asked Answered
E

7

20

I've got a form with a number of panels, each of which has Align=alTop, so they stack down nicely from the top of the form.

However, I want to dynamically change the appearance order of these panels - i.e, move them up and down. What's the best way of doing this?

Eaddy answered 11/8, 2009 at 11:39 Comment(0)
W
39

You can easily move a top-aligned panel to the top by setting its Top property to 0. Do this in reverse requested order (bottom panel first) and you are done.

Wavelength answered 11/8, 2009 at 16:9 Comment(2)
Sometimes if you assign a negative value it will work better. It worked for me in this way.Plankton
What if there is no "Top" property, like in FMX?Hurley
B
12

Move them the same way you'd move them at design time with the mouse: Set the current panel's Top property to one less than the Top property of the panel you want to be below the current panel. The VCL will take care of the rest.

If you have to move several panels, start with BeginDeferWindowPos. Adjust all the panels to whatever coordinates you want with DeferWindowPos, and then make them all move at once with EndDeferWindowPos.

Backspin answered 11/8, 2009 at 14:19 Comment(2)
Nice, I didn't know about DeferWindowPos. But isn't DisableAlign/EnableAlign easier then?Shamble
@Ngln, with DeferWindowPos, the window doesn't actually move at all until you call EndDeferWindowPos. If you're moving many windows, that helps avoid flicker as the positions of some windows get updated before the others have moved. As far as I can tell, DisableAlign doesn't prevent controls from moving anywhere, just the parent's alignment enforcement. I can't judge which is better.Backspin
C
2

I suggest building a framework where you dynamically remove/add the forms from/to their parent control. In general, the order of creation/addition is the visual order, but from your question I understand you want the order to change during the application lifetime, so just changing the original creation order won't be enough.

In order to change the order, try:

  1. Hide the panels
  2. Remove the panels from their parent control
  3. Add the panels to their parent control in the new order you wish
  4. Show the panels
Crossbill answered 11/8, 2009 at 11:47 Comment(0)
L
1

How about trying a top-aligned TGridPanel with one column and n rows instead --- re-ordering top-aligned panels is a bit of a pain, really.

(Note: TGridPanel is available in Delphi 2007 and up, if I remember correctly).

Laminitis answered 11/8, 2009 at 12:2 Comment(2)
Nice idea, but my panels aren't actually placed directly on a form - they're on another panel-like component which gives a background effect, and the TGridPanel hides that. to keep the question simple I failed to mention this subtlety...Eaddy
Can't you set TGridPanel.ParentBackground to True? I thought TPanel descendants could be transparent this way...Laminitis
T
1

If you change the top of the panel the order of visually panel change.

Try this (all the panels aligned altop and with the same Height):

PANEL0
PANEL1
PANEL2
PANEL3
PANEL4

At OnClick event of all panels do this:

 TPanel(Sender).Top := TPanel(Sender).Top - TPanel(Sender).Height - 2;

If you click on a panel it moves up one position.

That's the idea. Change the Top X pixels.
At the same, if you do this:

   TPanel(Sender).Top := TPanel(Sender).Top - (TPanel(Sender).Height * 2)- 2; 

The panel up 2 positions.

ADDED: If you use Drag&Drop, this events return the position (X and Y); With the original position and end position you can calculate the wew top for asign to the panel.

Excuse form my poor english. regards

Teaser answered 11/8, 2009 at 12:10 Comment(0)
M
1

I've used the following code:

procedure Show_Hide (Flag_Show : boolean);
begin
  if Flag_Show then
  begin
    with Panel_1 do begin Align := alTop; Visible := true; end;
    with Panel_2 do begin Align := alTop; Visible := true; end;
    with Panel_3 do begin Align := alTop; Visible := true; end;
    with Panel_4 do begin Align := alTop; Visible := true; end;
  end else
  begin
    with Panel_1 do begin Visible := false; Align := alNone; end;
    with Panel_2 do begin Visible := false; Align := alNone; end;
    with Panel_3 do begin Visible := false; Align := alNone; end;
    with Panel_4 do begin Visible := false; Align := alNone; end;
  end;
end;

according my wish Panel_1 Panel_2 Panel_3 Panel_4

Massenet answered 5/11, 2015 at 8:14 Comment(0)
S
0

I know its an old post but basically helped me - the idea of setting the top property to zero. I cant use the idea of programatically set the position cause this is up to the app user - it can chose to display some charts on the app and then, all the panels (parent) of the the teecharts are align altop. I set their top property to 0 on the inverse order and then just set visible true or false according to user input...

Thanks.

Shelve answered 18/12, 2009 at 1:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.