如何在添加 BorderLayout 后自动调整剩余元素的大小?

How to automatically resize the remaining elements after adding a BorderLayout?

我在应用程序中添加了一个简单的 statusBar。正常工作,根据分辨率调整大小

只是通过添加这个状态栏,突然间应用程序中的其他元素,例如文本字段或table,失去了“调整元素”的能力。

如果我们删除代码中的这三行,我将失去状态栏,但其他元素会根据我的需要进行调整。

  Container contentPane = frame.getContentPane();
  contentPane.setLayout(new BorderLayout());
  contentPane.add(statusBar, BorderLayout.SOUTH);

如何使 statusBar 和其他元素都调整到大小?

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

import java.io.IOException;
import java.sql.SQLException;


public class Menu {
    static void MenuBar() throws SQLException, IOException {

       
    JFrame frame = new JFrame("frame");
    JMenuBar menuBar = new JMenuBar();


    frame.setJMenuBar(menuBar);
    frame.setSize(1600, 1000);
    frame.setVisible(true); //If I delete any more, all the content will disappear
    frame.setContentPane(new Recipe().Main);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new BorderLayout());

    JStatusBar statusBar = new JStatusBar();
    JLabel leftLabel = new JLabel("App");
    statusBar.setLeftComponent(leftLabel);


    final JLabel timeLabel = new JLabel();
    timeLabel.setHorizontalAlignment(JLabel.CENTER);
    statusBar.addRightComponent(timeLabel);

    contentPane.add(statusBar, BorderLayout.SOUTH);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);

}

}

作为概念证明,我稍微修改了您的代码以向您展示我的意思:

public class Menu {
    void MenuBar() throws SQLException, IOException {

        JFrame frame = new JFrame("frame");
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(new JMenu("Main Menu"));

        frame.setJMenuBar(menuBar);
        frame.setSize(600, 400);
        
        JPanel center = new JPanel();
        center.add(new JLabel("CENTER"));

        Container contentPane = frame.getContentPane();
        contentPane.add(center, BorderLayout.CENTER);

        JPanel south = new JPanel();
        south.add(new JLabel("SOUTH"));
        south.setBackground(Color.green);
        JLabel leftLabel = new JLabel("App");
//    statusBar.setLeftComponent(leftLabel);

        final JLabel timeLabel = new JLabel();
        timeLabel.setHorizontalAlignment(JLabel.CENTER);
//    statusBar.addRightComponent(timeLabel);

        contentPane.add(south, BorderLayout.SOUTH);
        
        JPanel east = new JPanel();
        east.add(new JLabel("EAST"));
        east.setBackground(Color.cyan);
        contentPane.add(east, BorderLayout.EAST);
        
        JPanel west = new JPanel();
        west.add(new JLabel("WEST"));
        west.setBackground(Color.yellow);
        contentPane.add(west, BorderLayout.WEST);

        JPanel north = new JPanel();
        north.add(new JLabel("NORTH"));
        north.setBackground(Color.orange);
        contentPane.add(north, BorderLayout.NORTH);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//      frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            
            @Override
            public void run() {
                Menu menu = new Menu();
                try {
                    menu.MenuBar();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
    }
}

上面的代码产生以下结果(不调用 pack() 以遵守框架的设置大小)

正如您从上面的代码中看到的,我没有在框架的内容窗格中添加 new BorderLayout 因为当您实例化时它已经默认包含一个通过 JFrame 的内容窗格。我只是简单地使用它并在这个布局管理器指定的不同区域设置组件。

调整框架大小

不同的布局管理器在调整大小事件期间执行不同的行为。这完全取决于布局管理器。例如,JPanel 默认使用 FlowLayout。根据面板呈现时的大小,您会看到 JPanel 内的组件从左到右排列。当不再有 space(由面板的边界定义)时,您将看到组件排列在第一个组件下方的“行”上。这意味着,如果您在调整大小时减小面板的宽度,您应该会看到组件被包裹并堆叠在该面板内的其他组件之上。相反,如果您使用 GridLayout 并调整面板大小,则行为完全不同。您甚至可以限制设置最小 and/or 最大尺寸以限制组件应该调整多少或多少以及首选尺寸属性,该属性不同于“无布局管理器”时容器的“尺寸”属性是首选。这称为“绝对定位”,当您想要完全控制组件应位于的实际(x,y)坐标时,它就会完成布局管理器设置为 null。当然,这不是优选的。最好(在我看来)将此职责委托给 Java Swing 附带的各种布局管理器,或者自己编写一个(编写一个说起来容易做起来难)。我说了这么多是为了说我在评论部分发表的同样的话:

Spend some time reading the Oracle Tutorials on Layout Managers to get a glimpse of what Layout Managers come by default with different Swing components.

这还将帮助您了解当(例如)调整大小事件发生时预期的行为以及您需要在代码中执行哪些操作来调整此行为以满足您的需要。例如,如果您需要创建西洋跳棋或国际象棋应用程序,很明显您需要一个带有 GridLayout 管理器的容器。但是你可以调整它来定义最小和最大尺寸、首选尺寸等。

此外,Andrew Thompson 提到了一些非常重要的事情...您需要知道何时调用某些方法。他特别提到什么时候调用pack()setVisible()。像这样的小事(不是真的很少)可以有所作为。