BoxLayout игнорирует выравнивание подпанелей

У меня есть JPanel с менеджером BoxLayout, который содержит подпанели. Я хочу, чтобы компоненты внутри этих подпанелей имели выравнивание по левому краю, но всегда отображались по центру. Похоже, что BoxLayout правильно выравнивает компоненты, которые вставляются напрямую, но не может этого сделать, когда они находятся внутри подпанели.

Я изменил пример из http://www.java2s.com/Tutorial/Java/0240__Swing/YAxisAlignment.htm, поэтому каждая кнопка помещается внутри подпанели, а затем подпанель помещается внутрь главной панели с менеджером BoxLayout:

public class YAxisAlignX {
  private static Container makeIt(String title, float alignment) {
    String labels[] = { "--", "----", "--------", "------------" };

    JPanel container = new JPanel();
    container.setBorder(BorderFactory.createTitledBorder(title));
    BoxLayout layout = new BoxLayout(container, BoxLayout.Y_AXIS);
    container.setLayout(layout);

    // modified loop. the original version does not create JPanel pan.
    // adds the buttons directly the the JPanel container with the
    // BoxLayout
    for (int i = 0, n = labels.length; i < n; i++) {
      JPanel pan = new JPanel();
      JButton button = new JButton(labels[i]);
      pan.add(button);
      button.setAlignmentX(alignment);
      pan.setAlignmentX(alignment);
      container.add(pan);
    }
    return container;
  }

  public static void main(String args[]) {
    JFrame frame = new JFrame("Alignment Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Container panel1 = makeIt("Left", Component.LEFT_ALIGNMENT);
    Container panel2 = makeIt("Center", Component.CENTER_ALIGNMENT);
    Container panel3 = makeIt("Right", Component.RIGHT_ALIGNMENT);

    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new FlowLayout());
    contentPane.add(panel1);
    contentPane.add(panel2);
    contentPane.add(panel3);

    frame.pack();
    frame.setVisible(true);
  }
}

Если вы запустите эту версию, вы увидите, что все кнопки расположены по центру, несмотря на установленное выравнивание. Почему это происходит? Есть ли решение? В моем случае каждая подпанель содержит несколько компонентов, и я не хочу добавлять их прямо в основную панель.

Спасибо большое.


person karmapolice    schedule 25.07.2014    source источник


Ответы (1)


Но они согласованы!

Прежде всего, setAlignmentX изменяет свойство на уровне JComponent, макет, в котором размещены эти компоненты, может использовать или не использовать эту информацию. Например, BoxLayout использует его, а FlowLayout и BorderLayout нет.

В вашем случае вы размещаете несколько панелей с вертикальным BoxLayout и выравниваете их по-разному, и это работает! Так уж получилось, что панели растягиваются, чтобы соответствовать всей колонке, поэтому фактическое выравнивание не меняет их внешний вид. Вы можете увидеть это, установив границу вокруг панелей:

pan.setBorder(BorderFactory.createLineBorder(Color.red));

Видеть:

введите здесь описание изображения

То, что панели содержат кнопку или что-то еще, по большей части не имеет значения (влияет только на размер, который хочет занять панель, и то не однозначно), BoxLayout выравнивает панели, а не то, что там внутри панелей, это работа каждого компоновка панели. Вот почему BoxLayout не повлияло бы на выравнивание кнопок.

Теперь, как эти кнопки определяют его выравнивание? Ну, это зависит от макета, в котором они находятся. Кнопки находятся внутри панели pan, которая использует LayoutManager по умолчанию FlowLayout. Теперь, как я уже сказал, FlowLayout не заботится о свойстве AlignmentX/Y, поэтому строка:

button.setAlignmentX(alignment);

Ничего не достигает. Чтобы выровнять в FlowLayout, вам нужно изменить его поле alignment на FlowLayout.setAligment(int) (docs), вы также можете сделать это в конструкторе, поэтому если мы изменим объявление pan на:

JPanel pan = new JPanel(new FlowLayout(FlowLayout.LEFT));

У вас также будут кнопки, выровненные слева внутри их панелей:

//img

Разумеется, все столбцы выровнены по левому краю, так как параметр float alignment из makeIt не влияет на выравнивание FlowLayout, а только BoxLayout (и это не имеет значения). Возможно, вы захотите изменить этот аргумент на int и вызвать функцию с другими константами FlowLayout.

В общем, в исходной версии строка button.setAlignmentX(alignment); имела смысл, потому что кнопки добавлялись прямо на панель container, а BoxLayout правильно их выравнивал:

введите здесь описание изображения

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

Я надеюсь, что это ясно.

person DSquare    schedule 25.07.2014