Почему 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]()
Ответы
Ответ 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());