Delphi: как программно настроить визуальный порядок компонентов с помощью align = alTop

У меня есть форма с несколькими панелями, каждая из которых имеет Align=alTop, поэтому они хорошо складываются сверху формы.

Однако я хочу динамически изменять порядок появления этих панелей, т.е. перемещать их вверх и вниз. Как лучше всего это сделать?


person Roddy    schedule 11.08.2009    source источник


Ответы (7)


Вы можете легко переместить панель, выровненную по верхнему краю, наверх, установив для свойства Top значение 0. Сделайте это в обратном порядке (сначала нижняя панель), и все готово.

person Uwe Raabe    schedule 11.08.2009
comment
Иногда, если вы присвоите отрицательное значение, оно будет работать лучше. Это сработало для меня таким образом. - person HOPE; 07.12.2015

Переместите их так же, как вы перемещаете их с помощью мыши во время разработки: установите свойство Top текущей панели на единицу меньше, чем свойство Top панели, которую вы хотите расположить под текущей панелью. Обо всем остальном позаботится VCL.

Если вам нужно переместить несколько панелей, начните с BeginDeferWindowPos. Настройте все панели на любые координаты, которые вы хотите, с помощью DeferWindowPos, а затем заставьте их все двигаться одновременно с помощью EndDeferWindowPos.

person Rob Kennedy    schedule 11.08.2009
comment
Хорошо, я не знал о DeferWindowPos. Но разве DisableAlign/EnableAlign не проще? - person NGLN; 05.11.2015
comment
@Ngln, с DeferWindowPos окно вообще не двигается, пока вы не вызовете EndDeferWindowPos. Если вы перемещаете много окон, это помогает избежать мерцания, поскольку положение некоторых окон обновляется до того, как перемещаются другие. Насколько я могу судить, DisableAlign не препятствует перемещению элементов управления в любом месте, а только обеспечивает принудительное выравнивание родителя. Я не могу судить, что лучше. - person Rob Kennedy; 05.11.2015

Я предлагаю создать структуру, в которой вы динамически удаляете/добавляете формы из/в их родительский элемент управления. Как правило, порядок создания/добавления является визуальным порядком, но из вашего вопроса я понимаю, что вы хотите, чтобы порядок менялся в течение срока службы приложения, поэтому простого изменения исходного порядка создания будет недостаточно.

Чтобы изменить порядок, попробуйте:

  1. Скрыть панели
  2. Удалить панели из родительского контроля
  3. Добавьте панели к их родительскому элементу управления в желаемом новом порядке.
  4. Показать панели
person Roee Adler    schedule 11.08.2009

Как насчет того, чтобы вместо этого попробовать выровненный по верхнему краю TGridPanel с одним столбцом и n строками --- переупорядочить панели с выравниванием по верхнему краю на самом деле немного сложно.

(Примечание: TGridPanel доступно в Delphi 2007 и выше, если я правильно помню).

person onnodb    schedule 11.08.2009
comment
Хорошая идея, но мои панели на самом деле не размещены непосредственно в форме — они находятся в другом компоненте, похожем на панель, который создает фоновый эффект, а TGridPanel скрывает это. чтобы не усложнять вопрос, я не упомянул эту тонкость... - person Roddy; 11.08.2009
comment
Вы не можете установить TGridPanel.ParentBackground на True? Я думал, что потомки TPanel могут быть прозрачными таким образом... - person onnodb; 12.08.2009

Если вы измените верхнюю часть панели, порядок визуально панели изменится.

Попробуйте это (все панели выровнены altop и с одинаковой высотой):

ПАНЕЛЬ0
ПАНЕЛЬ1
ПАНЕЛЬ2
ПАНЕЛЬ3
ПАНЕЛЬ4

В событии OnClick всех панелей сделайте следующее:

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

Если вы нажмете на панель, она переместится на одну позицию вверх.

Это идея. Измените Верхние X пикселей.
В то же время, если вы сделаете это:

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

Панель вверх на 2 позиции.

ДОБАВЛЕНО: если вы используете Drag&Drop, эти события возвращают позицию (X и Y); С исходной позицией и конечной позицией вы можете рассчитать вершину для привязки к панели.

Извините за мой плохой английский. С Уважением

person Germán Estévez -Neftalí-    schedule 11.08.2009

Я использовал следующий код:

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;

по моему желанию Panel_1 Panel_2 Panel_3 Panel_4

person Hristo Markow    schedule 05.11.2015

Я знаю, что это старый пост, но в основном мне помогла идея установить свойство top равным нулю. Я не могу использовать идею программной установки позиции, потому что это зависит от пользователя приложения - он может выбрать отображение некоторых диаграмм в приложении, а затем все панели (родительские) диаграмм выравниваются по высоте. Я устанавливаю для их свойства top значение 0 в обратном порядке, а затем просто устанавливаю visible true или false в зависимости от ввода пользователя...

Спасибо.

person ronaldosantana    schedule 18.12.2009