Java Swing-setResizeable(true)使JFrame标题栏更高,窗口大小更小

Java Swing-setResizeable(true)使JFrame标题栏更高,窗口大小更小,java,swing,jframe,Java,Swing,Jframe,如果有人将其标记为重复,我会自己做:很久以前,我们有一个非常相关的问题: 没有一个解决方案适合我。这是我的SSCCE: import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.Com

如果有人将其标记为重复,我会自己做:很久以前,我们有一个非常相关的问题:

没有一个解决方案适合我。这是我的SSCCE:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;

public class TitleHeightChange extends JFrame {
    private static final String lp = System.lineSeparator();
    public TitleHeightChange() {
        begin();
    }

    private void begin() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//        UIManager.installLookAndFeel("Nimbus", NimbusLookAndFeel.class.getName());


        JFrame frame1 = new JFrame();
        frame1.setTitle("Frame1");
        frame1.setLayout(new BorderLayout());
        JTextArea area1 = new JTextArea();
        area1.setBorder(BorderFactory.createLineBorder(Color.darkGray,1));
        frame1.add(area1, BorderLayout.CENTER);

        frame1.addComponentListener(new ComponentListener() {

            @Override
            public void componentShown(ComponentEvent e) {
                // TODO Auto-generated method stub
                area1.setText("frame height: " + frame1.getBounds().height + lp
                        + "frame width: " + frame1.getBounds().width + lp
                        + "content pane height: " + frame1.getContentPane().getBounds().height + lp
                        + "content pane width: " + frame1.getContentPane().getBounds().width + lp
                        + "title bar height: " + (frame1.getBounds().height-frame1.getContentPane().getBounds().height) + lp
                        + "isResizable() value: false");
            }

            @Override
            public void componentResized(ComponentEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void componentMoved(ComponentEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void componentHidden(ComponentEvent e) {
                // TODO Auto-generated method stub

            }
        });
        frame1.setResizable(false);
        frame1.pack();
        frame1.setBounds(0, 0, 300, 300);
        frame1.setLocationRelativeTo(null);
        frame1.setVisible(true);

        JFrame frame2 = new JFrame();
        frame2.setTitle("Frame2");
        frame2.setLayout(new BorderLayout());
        JTextArea area2 = new JTextArea();
        area2.setBorder(BorderFactory.createLineBorder(Color.darkGray,1));
        frame2.add(area2, BorderLayout.CENTER);

        frame2.addComponentListener(new ComponentListener() {

            @Override
            public void componentShown(ComponentEvent e) {
                // TODO Auto-generated method stub
                area2.setText("frame height: " + frame2.getBounds().height + lp
                        + "frame width: " + frame2.getBounds().width + lp
                        + "content pane height: " + frame2.getContentPane().getBounds().height + lp
                        + "content pane width: " + frame2.getContentPane().getBounds().width + lp
                        + "title bar height: " + (frame2.getBounds().height-frame2.getContentPane().getBounds().height) + lp
                        + "isResizable() value: true");
            }

            @Override
            public void componentResized(ComponentEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void componentMoved(ComponentEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void componentHidden(ComponentEvent e) {
                // TODO Auto-generated method stub

            }
        });
        frame2.setResizable(true);
        frame2.pack();
        frame2.setBounds(0, 0, 300, 300);
        frame2.setLocationRelativeTo(null);
        frame2.setVisible(false);

        setLayout(new BorderLayout());
        JButton b = new JButton();
        b.setText("switch");
        b.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                if (frame1.isVisible()) {
                    frame1.setVisible(false);
                    frame2.setVisible(true);
                } else {
                    frame1.setVisible(true);
                    frame2.setVisible(false);
                }
            }
        });
        b.setBounds(0, 0, 100, 30);
        add(b, BorderLayout.CENTER);

        pack();
        setBounds(600, 700, 100, 30);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                TitleHeightChange frame = new TitleHeightChange();

            }

        });
    }
}
我注意到不仅窗口会改变大小,标题栏也会改变高度。使用此GIF可以更好地说明这一点:

我们可以在这个例子中看到我们需要的所有数据。当框架无法调整大小时:

frame height: 300
frame width: 300
content pane height: 274
content pane width: 294
title bar height: 26
isResizable() value: false
frame height: 300
frame width: 300
content pane height: 264
content pane width: 284
title bar height: 36
isResizable() value: true
当框架可调整大小时:

frame height: 300
frame width: 300
content pane height: 274
content pane width: 294
title bar height: 26
isResizable() value: false
frame height: 300
frame width: 300
content pane height: 264
content pane width: 284
title bar height: 36
isResizable() value: true
因此,当一个框架被设置为不可调整大小时,其内容窗格将添加一个(5,5,5,5)的插入,并且为了保持JFrame的总大小,标题栏将缩小10像素????这是荒谬的

我已经测试过使用和不使用Nimbus L&F,这是不相关的

这怎么可能和被容忍

我找到的解决方案是,在
pack()
之后,在可调整大小的窗口添加10个像素。但这是丑陋的,它并不能阻止标题栏的增加


我们如何解决这个问题?

毕竟这是一个外观问题

如果我们使用Java默认金属外观,并在创建两个框架之前设置
setDefaultLookAndFeelDecorated(true)
,Java默认外观样式的边框/插图将被绘制并可见,因此两个JFrames具有相同的宽度和高度

我玩过其他L&F,发现
javax.swing.plaf.nimbus.NimbusLookAndFeel
com.sun.java.swing.plaf.windows.windowslokandfeel
com.sun.java.swing.plaf.motif.motif.motif lookandfeel
没有实现这个额外的拖动处理程序,可能是出于美观的原因。(我真的很怀疑为什么Java默认风格想要绘制这个处理程序。我个人认为它不是牢不可破的。我认为实现其他L&F的ppl也希望避免它,所以他们提出了一个可用但丑陋的解决方案。)

此GIF显示默认金属L&F如何在两个帧中绘制调整大小的“句柄”:
毕竟这是一个外观问题

如果我们使用Java默认金属外观,并在创建两个框架之前设置
setDefaultLookAndFeelDecorated(true)
,Java默认外观样式的边框/插图将被绘制并可见,因此两个JFrames具有相同的宽度和高度

我玩过其他L&F,发现
javax.swing.plaf.nimbus.NimbusLookAndFeel
com.sun.java.swing.plaf.windows.windowslokandfeel
com.sun.java.swing.plaf.motif.motif.motif lookandfeel
没有实现这个额外的拖动处理程序,可能是出于美观的原因。(我真的很怀疑为什么Java默认风格想要绘制这个处理程序。我个人认为它不是牢不可破的。我认为实现其他L&F的ppl也希望避免它,所以他们提出了一个可用但丑陋的解决方案。)

此GIF显示默认金属L&F如何在两个帧中绘制调整大小的“句柄”: