Java JFrame.getInsets值

Java JFrame.getInsets值,java,swing,java-11,Java,Swing,Java 11,在Windows 10上采用OpenJDK 11。JFrame子代构造函数: getGraphicsConfiguration().getBounds() java.awt.Rectangle[x=0,y=0,width=2560,height=1440] Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration()) java.awt.Insets[top=0,left=0,bottom=40,right=0]

在Windows 10上采用OpenJDK 11。JFrame子代构造函数:

getGraphicsConfiguration().getBounds()
java.awt.Rectangle[x=0,y=0,width=2560,height=1440]

Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration())
java.awt.Insets[top=0,left=0,bottom=40,right=0]

set*Size(new Dimension(2560, 1400));

pack();

getSize();
java.awt.Dimension[width=2560,height=1400]

getInsets();
java.awt.Insets[top=31,left=8,bottom=8,right=8]

getContentPane().getSize()
java.awt.Dimension[width=2544,height=1361]
。。。然而,除了任务栏外,该窗口并没有覆盖整个桌面空间(因为有8个额外的插入)。为什么?

使用我的答案的示例代码:

package javaapplication2;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GraphicsConfiguration;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;

public final class TestFrame extends JFrame {

    private static final long serialVersionUID = 1L;

    private static final class CustomPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        public CustomPanel(Dimension d) {
            setMinimumSize(d);
            setPreferredSize(d);
            setMaximumSize(d);
            //this is just an example, there is custom layout code here, not using Swing, but it needs Dimension d to work
        }

    }

    public TestFrame() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));

        GraphicsConfiguration gc = getGraphicsConfiguration();
        Rectangle screenBounds = gc.getBounds();
        Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
        Dimension expectedFrameSize = new Dimension(screenBounds.width - screenInsets.left - screenInsets.right, screenBounds.height - screenInsets.top - screenInsets.bottom);

        setExtendedState(JFrame.MAXIMIZED_BOTH);
        setVisible(true);
        Dimension frameSize = getSize();
        Insets frameInsets = getInsets();
        setVisible(false);
        Dimension contentSize = new Dimension(frameSize.width - frameInsets.left - frameInsets.right, frameSize.height - frameInsets.top - frameInsets.bottom);
        getContentPane().add(new CustomPanel(contentSize));

        setVisible(true);
        setResizable(false);

        System.out.println("screenBounds " + screenBounds);
        System.out.println("screenInsets " + screenInsets);
        System.out.println("expectedFrameSize " + expectedFrameSize);
        System.out.println("frameSize " + frameSize);
        System.out.println("frameInsets " + frameInsets);
        System.out.println("contentSize " + contentSize);
        System.out.println("assert expectedFrameSize == frameSize " + expectedFrameSize.equals(frameSize));
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestFrame().setVisible(true);
            }
        });
    }

}
我希望能够计算
维度
,而不使窗口暂时可见。但使用JDK中可用的方法不可能获得正确的大小:

getGraphicsConfiguration().getBounds()
Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration())

显然,最大化帧的大小大于实际屏幕,并且帧插入包括8,8,8,8像素(在我的窗口上),其中一些在实际帧之外。获得用于最大化窗口的实际帧大小的唯一方法是使其在一段时间内可见。最后,我采取了这个骗局:

      setExtendedState(JFrame.MAXIMIZED_BOTH);
      setVisible(true);
      Dimension size = getSize();
      Insets insets = getInsets();
      setVisible(false);
      dimension = new Dimension(size.width - insets.left - insets.right, size.height - insets.top - insets.bottom);
这使我能够找出框架内容窗格的尺寸,框架占用所有桌面空间(屏幕减去任务栏)。只有在final
setVisible(true)
之后才能调用
setresizeable(false)

看看这些数字对你是否有意义:

屏幕边界
java.awt.Rectangle[x=0,y=0,宽度=2560,高度=1440]

屏幕插图
java.awt.insets[top=0,left=0,bottom=40,right=0]

帧大小
java.awt.Dimension[宽度=2576,高度=1416]

框架插图
java.awt.insets[top=31,left=8,bottom=8,right=8]

计算尺寸
java.awt.dimension[宽度=2560,高度=1377]


帧大小在每个方向上比屏幕空间(屏幕边界减去屏幕插入)大16。这些额外的像素包括在帧插入中,即使它们不在帧中。

显然,最大化帧的大小大于实际屏幕,帧插入包括8,8,8,8像素(在我的窗口上),其中一些像素在实际帧之外。获得用于最大化窗口的实际帧大小的唯一方法是使其在一段时间内可见。最后,我采取了这个骗局:

      setExtendedState(JFrame.MAXIMIZED_BOTH);
      setVisible(true);
      Dimension size = getSize();
      Insets insets = getInsets();
      setVisible(false);
      dimension = new Dimension(size.width - insets.left - insets.right, size.height - insets.top - insets.bottom);
这使我能够找出框架内容窗格的尺寸,框架占用所有桌面空间(屏幕减去任务栏)。只有在final
setVisible(true)
之后才能调用
setresizeable(false)

看看这些数字对你是否有意义:

屏幕边界
java.awt.Rectangle[x=0,y=0,宽度=2560,高度=1440]

屏幕插图
java.awt.insets[top=0,left=0,bottom=40,right=0]

帧大小
java.awt.Dimension[宽度=2576,高度=1416]

框架插图
java.awt.insets[top=31,left=8,bottom=8,right=8]

计算尺寸
java.awt.dimension[宽度=2560,高度=1377]


帧大小在每个方向上比屏幕空间(屏幕边界减去屏幕插入)大16。而那些额外的像素包括在框架插图中,即使它们不在框架中。

框架的插图描述了窗口装饰的大小,其中可能包括半透明边框。在MicrosoftWindows上,还有一个联系,即在早期版本中,窗口边框的厚度通常为8像素

当您最大化窗口时,其边界的设置方式将使这些插入位于可见区域之外,但标题栏的某些部分保持可见。更糟糕的是,当窗口被最大化时,标题栏会改变其布局,从而减少边距空间

但是,当您正在寻找仅适用于Windows的解决方案时,遗留方面可能会有所帮助。“文章”。正如它所解释的,窗口将始终处于(-n,-n),并且对于边框大小n,窗口的实际可见区域将大于(2n×2n),以便与旧软件兼容。但是,正如它所解释的,最大化模式是特殊的,因为这些边界总是被切断的,所以它们不会出现在其他监视器中,也不会出现在任务栏上

这就是为什么仅仅通过设置边界来模拟相同的行为是不可能的。不仅标题栏的格式副本不同,还可以使部分窗口显示在多监视器系统的其他监视器中以及任务栏上

因此,利用这些知识,您可以预测内容窗格的大小:

JFrame frame = new JFrame("Max");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setExtendedState(Frame.MAXIMIZED_BOTH);

Timer t = new Timer(1000, ev -> System.out.println("actual size is "
    +frame.getContentPane().getWidth()+" x "+frame.getContentPane().getHeight()));
t.setRepeats(false);
t.start();

Rectangle scrBounds = frame.getGraphicsConfiguration().getBounds();
Insets scrInsets = frame.getToolkit().getScreenInsets(frame.getGraphicsConfiguration());
Insets winInsets = frame.getInsets();

int width = scrBounds.width - scrInsets.left - scrInsets.right;
int height = scrBounds.height - scrInsets.top - scrInsets.bottom
                              - winInsets.top + winInsets.bottom;

System.out.println("content pane size will be "+width+" x "+height);

frame.setVisible(true);

这假设所有边缘的历史边框厚度都相同,因此我们可以使用
底部
大小来确定顶部大小和标题栏大小,因此
顶部-底部
为我们提供剩余的标题栏大小。

框架的插图描述窗口装饰的大小,其中可能包括半透明边框。在MicrosoftWindows上,还有一个联系,即在早期版本中,窗口边框的厚度通常为8像素

当您最大化窗口时,其边界的设置方式将使这些插入位于可见区域之外,但标题栏的某些部分保持可见。更糟糕的是,当窗口被最大化时,标题栏会改变其布局,从而减少边距空间

但是,当您正在寻找仅适用于Windows的解决方案时,遗留方面可能会有所帮助。“文章”。正如它所解释的,窗口将始终处于(-n,-n),并且对于边框大小n,窗口的实际可见区域将大于(2n×2n),以便与旧软件兼容。但是,正如它所解释的,最大化模式是特殊的,因为这些边界总是被切断的,所以它们不会出现在其他监视器中,也不会出现在任务栏上

这就是为什么仅仅通过设置边界来模拟相同的行为是不可能的。不仅标题栏的格式副本不同,还可以使部分窗口显示在多监视器系统的其他监视器中以及任务栏上

因此,利用这些知识,您可以预测内容窗格的大小:

JFrame frame = new JFrame("Max");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setExtendedState(Frame.MAXIMIZED_BOTH);

Timer t = new Timer(1000, ev -> System.out.println("actual size is "
    +frame.getContentPane().getWidth()+" x "+frame.getContentPane().getHeight()));
t.setRepeats(false);
t.start();

Rectangle scrBounds = frame.getGraphicsConfiguration().getBounds();
Insets scrInsets = frame.getToolkit().getScreenInsets(frame.getGraphicsConfiguration());
Insets winInsets = frame.getInsets();

int width = scrBounds.width - scrInsets.left - scrInsets.right;
int height = scrBounds.height - scrInsets.top - scrInsets.bottom
                              - winInsets.top + winInsets.bottom;

System.out.println("content pane size will be "+width+" x "+height);

frame.setVisible(true);
这假设所有边的历史边框厚度相同,因此我们可以使用
底部
大小来确定顶部大小和标题栏大小,因此
顶部-底部