BoxLayout отказывается соблюдать предпочтительный размер JButton

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

Вот мой код на данный момент:

import java.awt.*;
import javax.swing.*;



public class Main 
{
    public static void main(String[] args)
    {
      JFrame.setDefaultLookAndFeelDecorated(true);
      JFrame frame = new JFrame("Suit-Up");
      frame.setContentPane(makeGUI());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(900,450);
      frame.setLocationRelativeTo(null);
      frame.setResizable(false);
      frame.setVisible(true);
    }

    public static JPanel makeGUI()
    {
      JPanel main = new JPanel();
      main.setMinimumSize(new Dimension(900,450));
      main.setBackground(Color.red);

      JPanel infoPanel = new JPanel();
      infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.LINE_AXIS));
      infoPanel.setPreferredSize(new Dimension(900,60));
      infoPanel.setBackground(Color.green);
      main.add(infoPanel);

      JPanel infoText = new JPanel();
      infoText.setLayout(new BoxLayout(infoText, BoxLayout.PAGE_AXIS));
      infoPanel.add(infoText);

      JPanel moneyText = new JPanel();
      moneyText.setLayout(new BoxLayout(moneyText, BoxLayout.LINE_AXIS));
      infoText.add(moneyText);

      JPanel lastGameText = new JPanel();
      lastGameText.setLayout(new BoxLayout(lastGameText, BoxLayout.LINE_AXIS));
      infoText.add(lastGameText);

      JButton playAgain = new JButton("Play Again ($20)");
      playAgain.setPreferredSize(new Dimension(200,60));
      infoPanel.add(playAgain);

      JButton finish = new JButton("End Session");
      finish.setPreferredSize(new Dimension(200,60));
      infoPanel.add(finish);

      JPanel cardPanel = new JPanel();
      cardPanel.setLayout(new BoxLayout(cardPanel, BoxLayout.LINE_AXIS));
      main.add(cardPanel);

      return main;
    }
}

Несмотря на указание предпочтительных размеров для обоих JButton, они не меняют свои размеры. Я также пробовал setMaximumSize() и setMinimumSize(), но ни один из них не дал никакого эффекта.

Я упускаю из виду что-то очевидное или это ограничение BoxLayout?


person Thrfoot    schedule 09.01.2013    source источник
comment
вы всегда можете использовать BoxLayout, но вложите компоненты ...   -  person mre    schedule 09.01.2013
comment
Извините, но я не совсем понимаю, что вы имеете в виду под вложенностью. Я относительно новичок в менеджерах по расположению.   -  person Thrfoot    schedule 09.01.2013
comment
если вы поместите кнопку на панель и добавите панель непосредственно в контейнер вместо кнопки, размер панели будет изменен вместо кнопки.   -  person mre    schedule 09.01.2013


Ответы (1)


«Насколько мне известно, LayoutManager обычно учитывает предпочтительный размер любого компонента» - на самом деле это не так. предпочтительный / минимальный / максимальный размер - это просто «подсказки», которые менеджеры по расположению МОГУТ использовать, чтобы определить, как лучше всего расположить содержимое. Менеджеры по компоновке могут просто игнорировать их, если хотят.

Из JavaDocs

BoxLayout пытается расположить компоненты по их предпочтительной ширине (для горизонтальной компоновки) или высоте (для вертикальной компоновки). Для горизонтального макета, если не все компоненты имеют одинаковую высоту, BoxLayout пытается сделать все компоненты такими же высокими, как самый высокий компонент. Если это невозможно для конкретного компонента, BoxLayout выравнивает этот компонент по вертикали в соответствии с выравниванием компонента по оси Y. По умолчанию компонент имеет выравнивание по Y 0,5, что означает, что вертикальный центр компонента должен иметь такую ​​же координату Y, что и вертикальные центры других компонентов с выравниванием 0,5 по оси Y.

Точно так же для вертикального макета BoxLayout пытается сделать все компоненты в столбце такой же шириной, как самый широкий компонент. Если это не удается, он выравнивает их по горизонтали в соответствии с их выравниванием по оси X. Для макета PAGE_AXIS горизонтальное выравнивание выполняется на основе переднего края компонента. Другими словами, значение выравнивания X, равное 0,0, означает левый край компонента, если ComponentOrientation контейнера находится слева направо, и в противном случае означает правый край компонента.

person MadProgrammer    schedule 09.01.2013
comment
Тем не менее, проблем с предпочтительными размерами, которые я использовал, быть не должно. Там достаточно места для JButton в JPanel, они просто отказываются изменять свой размер чем-либо, кроме добавления текста к своим ярлыкам. Я прочитал документацию, но не видел ничего, что объясняло бы то, с чем я сейчас сталкиваюсь. - person Thrfoot; 09.01.2013
comment
@Thrfoot Я запустил вам тестовый код и BoxLayout просто отказывается использовать preferredSize из JButton независимо от того, что я пробовал. Как правило, не рекомендуется манипулировать предпочтительным размером компонентов таким образом, обычно нам рекомендуется использовать либо менеджеры компоновки, либо напрямую переопределять метод getPreferredSize. Как ни странно, FlowLayout работал нормально ... - person MadProgrammer; 09.01.2013
comment
Странно ... Ну, тогда я не смогу заставить его работать с BoxLayout. Вы бы порекомендовали какие-либо другие менеджеры по расположению, с которыми я могу получить более или менее похожий эффект? - person Thrfoot; 09.01.2013
comment
@Thrfoot Если вы устанавливаете равную ширину и высоту, попробуйте использовать FlowLayout, выровненный по левому краю ... - person MadProgrammer; 09.01.2013
comment
Вот и получилось! Спасибо! Думаю, иногда что-то просто не работает. - person Thrfoot; 09.01.2013
comment
Ответ - вызвать boxLayout.invalidateLayout (container); Это очистит предыдущие предпочтительные размеры, которые он кэшировал, запросит новые у компонентов и соответствующим образом отрегулирует. - person AdrianVeidt; 19.09.2013