JFrame/BoxLayout 奇怪的大小行为

JFrame/BoxLayout weird size behavior

我正在尝试使用 BoxLayout 在 JPanel 中正确设置我的 JButton 的大小,但行为非常奇怪。 它将从 JButton.setPreferredSize 获取高度,但完全忽略宽度。这也仅在所有按钮设置为相同高度时才有效。一旦一个更小,它就会将所有按钮恢复到某个随机的最小尺寸(所有按钮甚至都不相同)

我的代码是这样的:

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 500);

JPanel rightPanel = new JPanel();
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));

JButton bBookmarks = new JButton("Bookmarks");
bBookmarks.setPreferredSize(new Dimension(200, 100));
//more buttons with same size

leftPanel.add(bBookmarks);
//more buttons

JSplitPane mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
mainPanel.setDividerLocation(200);

frame.add(mainPanel);
frame.setResizable(false);
frame.setVisible(true);

这将创建此图像。

中间的按钮也总是比其他按钮宽。使用 frame.pack() 除了调整框架大小外什么都不做,因为右侧面板是空的。

我做错了什么?

编辑:应该是这样的:

分而治之:将设计分解为易于布局的小容器。在这种情况下,不要将按钮直接放在左侧 (BoxLayout) 容器中,而是使用 GridLayout 管理器放在嵌套的 JPanel 中。
这确保所有按钮具有相同的大小:

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);

    //add all buttons to a panel using a GridLayout which shows all components having the same size
    JPanel buttons = new JPanel(new GridLayout(0,1));
    JButton bBookmarks = new JButton("Bookmarks");  buttons.add(bBookmarks);
    JButton bPlotter = new JButton("Plotter");      buttons.add(bPlotter);
    JButton bShips = new JButton("Ships");          buttons.add(bShips);

    //add buttons and text area to a panel using BoxLayout
    JPanel leftPanel = new JPanel();
    leftPanel.setPreferredSize(new Dimension(100,400));
    leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
    leftPanel.add(buttons);
    leftPanel.add(new TextArea(10,30));

    JPanel rightPanel = new JPanel();
    rightPanel.setPreferredSize(new Dimension(600,400));
    rightPanel.add(new JLabel("right pane"));

    JSplitPane mainPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true, leftPanel, rightPanel);

    frame.add(mainPanel);
    frame.pack();
    frame.setVisible(true);