Подтвердить что ты не робот

Почему BoxLayout не позволит мне изменить ширину JButton, но позвольте мне изменить высоту?

Я пытаюсь получить Layout из JDialog моего, чтобы соответствовать определенному взгляду, что программа, в которой я переношу на Java, я использовал несколько LayoutManager с большим успехом, но по какой-то причине Кажется, я ничего не могу сделать. Моя цель состоит в том, чтобы правая (восточная) сторона JDialog содержала кнопку "Найти дальше" и "Отменить" в порядке сверху вниз, а затем дополнительное пространство ниже, чтобы две кнопки всегда находились в верхней части JDialog, но по какой-то причине BoxLayout постоянно игнорирует любые попытки изменения (это где я потерян) ширину a JButton. Далее следует код.

JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
cancel.setPreferredSize(new Dimension((int)findNext.getPreferredSize().getWidth(),  
    (int)cancel.getPreferredSize().getHeight()));

JPanel example = new JPanel();  
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));  
example.add(findNext);
example.add(cancel);  
example.add(Box.createGlue());  

Независимо от того, что я пытаюсь, cancel всегда сохраняет нормальный размер. Я пробовал setMinimumSize() и setMaximumSize() с теми же параметрами, что и setPreferredSize, не повезло. Я даже пробовал cancel.setPreferredSize(new Dimension(500, 500));, и высота кнопок была единственной корректированной, она STILL сохранила заданную по умолчанию ширину.

Чтобы прояснить любые вопросы, вот как это выглядит (теперь, когда я его закончил), и вы увидите, что кнопки "Найти дальше" и "Отмена" не имеют одинакового размера.

example image

4b9b3361

Ответ 1

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

Существует три метода, связанных с параметрами калибровки в Swing: setPreferredSize(), setMinimumSize() и setMaximumSize(). Однако важным моментом является то, что именно конкретный менеджер компоновки используется для того, признает ли он какой-либо из этих методов.

Для BoxLayout (макет, который использует оригинальный плакат):

  • setMinimumSize() - BoxLayout оценивает это.
  • setMaximumSize() - BoxLayout оценивает это.
  • setPreferredSize() - если используется X_AXIS, ширина считается выполненной, если используется Y_AXIS, высота выполняется

В OP используется Y_AXIS BoxLayout, поэтому изменяется только его высота.

Обновление: Я собрал страницу с этой же информацией для всех менеджеров макета. Надеюсь, это поможет некоторым искателям: http://thebadprogrammer.com/swing-layout-manager-sizing/

Ответ 2

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

example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
Box.createVerticalStrut(10);
example.add(cancel);

Приложение:

добавление в setMaximumSize() заставило его работать.

Это ожидаемое поведение для компонентов с одинаковой максимальной шириной в вертикальном BoxLayout, как описано в Особенности компоновки ящиков. Предпочтительная ширина контейнера становится равной (равно широким) детям, а выравнивание по X становится неуместным.

example.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
Dimension d = findNext.getMaximumSize();
cancel.setMaximumSize(new Dimension(d));
example.add(findNext);
example.add(cancel);

Ответ 3

Как упоминалось в комментариях к этому вопросу, вы смогли исправить его, переключившись на setMaximumSize(). Однако, как вы отметили, setPreferredSize() не работает. Итак, что с этим?

С многими вещами Swing свойства, используемые для определения фактического размера компонента при использовании BoxLayout, несколько случайны (на мой взгляд). При определении того, как визуализировать компоненты, Swing вызывает layoutComponent() в менеджере компоновки, который вычисляет, где размещать все.

BoxLayout реализация layoutComponent() включает вызов метода, который создает SizeRequirements объекты для ширины и высоты каждого компонентов, которые вы добавляете в JPanel, на основе их методов getMinimum/Preferred/MaximumSize().

Затем он вызывает SizeRequirements.calculateAlignedPositions() для определения правильных значений ширины для каждого компонента, потому что ваша ориентация BoxLayout.Y_AXIS (высоты вычисляются с использованием другого метода). Принимая фрагменты из источника, соответствующая реализация этого метода выглядит следующим образом:

for (int i = 0; i < children.length; i++) {
    SizeRequirements req = children[i];
    //...
    int maxAscent = (int)(req.maximum * alignment);
    int maxDescent = req.maximum - maxAscent;
    //...
    int descent = Math.min(totalDescent, maxDescent);
    //...
    spans[i] = (int)Math.min((long) ascent + (long)descent, Integer.MAX_VALUE);
}

Обратите внимание, что totalDescent - это доступная ширина, поэтому descent всегда устанавливается на maxDescent, которая основана на SizeRequirements.maximum, которая была взята из JButton.getMaximumSize(). Значение spans[i] затем используется позже при вызове JButton.setBounds() в качестве ширины. Как вы заметили, getPreferredSize() здесь никогда не участвовал, поэтому его установка не влияет на это.

Ответ 4

Обычно, если вы хотите обеспечить размер компонента в Swing, вам нужно вызвать setMinimumSize(), setMaximumSize() и SetPrefferedSize() с тем же значением.

Ответ 5

Если вы поместите свои кнопки в панель GridLayout, они будут иметь одинаковую ширину.

Ответ 6

button.setMaximumSize(getMaximumSize());