为什么 JFrame 的大小超过了其 ContentPane 的大小,即使它已定义大小?

Why does the size of the JFrame exceed the size of its ContentPane, even though it has a defined size?

我注意到秋千中容器之间的行为很奇怪。

为了举例说明测试,我创建了一个JFrame和一个JPanel,并将面板设置为contentPane。我将首选和最大 JPanel 大小定义为 400,300。所有这些都可以在下面的示例中看到:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ExcessiveSpacePanelTest {
    JFrame frame;
    JPanel panel;

    public void initGUI(){

        frame =  new JFrame();

        panel = new JPanel();
        panel.setBorder(BorderFactory.createLineBorder(Color.RED, 1));
        panel.setPreferredSize(new Dimension(400, 300));
        panel.setMaximumSize(new Dimension(400, 300));


        frame.setContentPane(panel);
        frame.pack();

        System.out.println("panel size: [" + panel.getSize().width + "," + panel.getSize().height +"]");
        System.out.println("frame size: [" + frame.getSize().width + "," + frame.getSize().height+"]");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() ->{
            new ExcessiveSpacePanelTest().initGUI();
        });
    }
}

结果是:

令我惊讶的是,终端的输出是:

panel size: [400,300]
frame size: [416,338]

我不明白为什么框架添加了这个额外的东西 space,即使组件中没有任何东西可以强制框架调整大小。

我试图通过在 pack(); 之前添加行 panel.setBorder (BorderFactory.createEmptyBorder(0, 0, 0, 0)); 来在面板上设置归零边缘,但结果仍然相同。

这个问题是 java 给了我一个错误的信息,因为面板在缩放框架的大小,从上面的结果,我们已经看到两者不是大小相同。

是否正确报告了这两项措施?为什么会出现这种情况?

您可能会发现比较不同平台上类似程序的结果很有帮助。特别是,

  • 红色的Border在面板里面;您的用法符合 API recommendation, "we recommend that you put the component in a JPanel and set the border on the JPanel."

  • 框架宽度与 Mac OS X 上的面板宽度匹配,因为用于 top-level container 的重量级对等 Mac 上没有垂直边框] OS X; Windows 点有自己的边界。

  • 框架高度包括拖动条和框架边框:Widows 为 38 像素,Mac OS X 为 22。

  • 当你真的想覆盖getPreferredSize()时,不要使用setPreferredSize()

  • 顺便说一句,框架的 add() 方法转发到内容窗格。

panel size: [400,300]
frame size: [400,322]

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ExcessiveSpacePanelTest {
    JFrame frame;
    JPanel panel;

    public void initGUI(){
        frame = new JFrame();
        panel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 300);
            }
        };
        panel.setBorder(BorderFactory.createLineBorder(Color.RED, 1));
        frame.add(panel);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);

        System.out.println("panel size: [" + panel.getSize().width + "," + panel.getSize().height +"]");
        System.out.println("frame size: [" + frame.getSize().width + "," + frame.getSize().height+"]");
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() ->{
            new ExcessiveSpacePanelTest().initGUI();
        });
    }
}