【问题标题】:Why does the JFrame setSize() method not set the size correctly?为什么 JFrame setSize() 方法没有正确设置大小?
【发布时间】:2011-09-29 09:59:10
【问题描述】:

所以我用java编程了一个学期左右,遇到过几次这个问题,终于有时间问了。

如果我创建一个JFrame 然后设置大小,例如setSize(400,800)。框架实际上并不长800 pixels。据我所知,它实际上更像770 (or maybe 769) pixels long。此外,如果您将垂直尺寸设置得非常低(低于 30),则框架甚至不会显示,只有操作系统的顶部窗口栏和框架不会变大,直到您达到超过 30 的值(所以setSize(400,0) 看起来与 setSize(400,20) 相同)。为什么会这样,不难修复,但很奇怪,我很好奇这是为什么?

如果您需要有关任何事情的更多信息,请询问,我会告诉您的。

【问题讨论】:

  • 您通常不必必须设置框架的大小。如果你这样做了,那就是麻烦的征兆。相反,为框架内的组件指定首选大小(如果可能,使用构造函数参数,例如new JTextArea(40,10)),或者通过在组件上设置首选大小并将它们添加到适当的布局/约束中。之后,pack() 框架 & 它将成为显示 GUI 所需的最小尺寸。
  • @Andrew:是什么让设置框架的大小变得“麻烦”?
  • @Logan:如果一个框架的唯一组件是一个 400x400 的渲染区域,那么框架需要多大才能容纳它?让 JRE 用pack() 解决这个问题。如果您还有其他问题,我建议您(然后搜索)提出您自己的问题。关于这个话题,要提及的内容远远超过评论中的内容。

标签: java swing jframe


【解决方案1】:

可能是因为框架的大小包括边框的大小。

Frame 是一个带有标题和边框的顶级窗口。框架的大小包括为边界指定的任何区域。可以使用 getInsets 方法获得边界区域的尺寸。由于边框区域包含在框架的整体大小中,因此边框有效地遮挡了框架的一部分,从而将可用于渲染和/或显示子组件的区域限制在左上角位置为 (insets. left, insets.top),并且具有宽度 - (insets.left + insets.right) 乘以高度 - (insets.top + insets.bottom) 的大小。

来源: http://download.oracle.com/javase/tutorial/uiswing/components/frame.html

【讨论】:

    【解决方案2】:

    JFrame SetSize() 包含区域+边框。

    我认为你必须设置ContentPane的大小

    jFrame.getContentPane().setSize(800,400);
    

    所以我建议您使用嵌入在 JFrame 中的 JPanel,然后在该 JPanel 上绘图。这将最大限度地减少您的问题。

    JFrame jf = new JFrame();
    JPanel jp = new JPanel();
    jp.setPreferredSize(new Dimension(400,800));// changed it to preferredSize, Thanks!
    jf.getContentPane().add( jp );// adding to content pane will work here. Please read the comment bellow.
    jf.pack();
    

    我从Javadoc读到这篇文章

    JFrame 类略 与Frame 不兼容。像所有人一样 其他 JFC/Swing 顶级容器, JFrame 包含 JRootPane 作为其 独生子女。提供的内容窗格 通常,根窗格应 包含所有非菜单组件 由JFrame 显示。这是 不同于 AWT Frame 的情况。为了 例如,将孩子添加到 AWT 你要写的框架:

    frame.add(child);

    但是使用 JFrame 您需要添加 孩子到JFrame 的内容窗格 而是:

    frame.getContentPane().add(child);

    【讨论】:

    • 请将jp.setSize( 400, 800 ); 更改为jp.setPreferredSize(new Dimension(400, 800)); 如果您将JPanel 添加到JFrame 然后jf.getContentPane().add( jp ) 是无用的,因为您调用相同的JComponents
    • @mKorbel,我已将其更改为 preferredSize,谢谢。但是关于第二点,我不是将JPanel 添加到JFrame,而是将JPanel 添加到JFrame 的孩子JRootPane。请阅读我最后添加的评论。
    • 再次,如果您添加与 JFrame.getContentPane().add(JPanel) 相同(使用 BorderLayout.CENTER)的 JFrame#add(JPanel),则无需将任何 JComponent 添加到 Swing 中的 ContentPane,无论如何+1
    【解决方案3】:

    设置框架大小的原因有很多。一种是记住用户设置的最后大小,并恢复这些设置。我有这个似乎对我有用的代码:

    package javatools.swing;
    import java.util.prefs.*;
    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.JFrame;
    
    public class FramePositionMemory {
        public static final String WIDTH_PREF = "-width";
    
        public static final String HEIGHT_PREF = "-height";
    
        public static final String XPOS_PREF = "-xpos";
    
        public static final String YPOS_PREF = "-ypos";
        String prefix;
        Window frame;
        Class<?> cls;
    
        public FramePositionMemory(String prefix, Window frame, Class<?> cls) {
            this.prefix = prefix;
            this.frame = frame;
            this.cls = cls;
        }
    
        public void loadPosition() {
            Preferences prefs = (Preferences)Preferences.userNodeForPackage(cls);
        //  Restore the most recent mainframe size and location
            int width = prefs.getInt(prefix + WIDTH_PREF, frame.getWidth());
            int height = prefs.getInt(prefix + HEIGHT_PREF, frame.getHeight());
            System.out.println("WID: " + width + " HEI: " + height);
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            int xpos = (screenSize.width - width) / 2;
            int ypos = (screenSize.height - height) / 2;
            xpos = prefs.getInt(prefix + XPOS_PREF, xpos);
            ypos = prefs.getInt(prefix + YPOS_PREF, ypos);
            frame.setPreferredSize(new Dimension(width, height));
            frame.setLocation(xpos, ypos);
            frame.pack();
        }
    
        public void storePosition() {
            Preferences prefs = (Preferences)Preferences.userNodeForPackage(cls);
            prefs.putInt(prefix + WIDTH_PREF, frame.getWidth());
            prefs.putInt(prefix + HEIGHT_PREF, frame.getHeight());
            Point loc = frame.getLocation();
            prefs.putInt(prefix + XPOS_PREF, (int)loc.getX());
            prefs.putInt(prefix + YPOS_PREF, (int)loc.getY());
            System.out.println("STORE: " + frame.getWidth() + " " + frame.getHeight() + " " + loc.getX() + " " + loc.getY());
        }
    }
    public class Main {
    void main(String[] args) {
            JFrame frame = new Frame();
            // SET UP YOUR FRAME HERE.
            final FramePositionMemory fm = new FramePositionMemory("scannacs2", frame, Main.class);
            frame.setSize(400, 400); // default size in the absence of previous setting
            fm.loadPosition();
    
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    fm.storePosition();
                }
            });
            frame.setVisible(true);
        }
    }
    

    }

    【讨论】:

      【解决方案4】:

      在 OS X 上,您需要考虑现有的窗口装饰。他们在高度上增加了 22 个像素。所以在 JFrame 上,你需要告诉程序这个:

      frame.setSize(width, height + 22);
      

      【讨论】:

        【解决方案5】:

        我知道这个问题大约有 6 年以上的历史,但 @Kyle 的回答不起作用。

        使用这个

        setSize(width - (getInsets().left + getInsets().right), height - (getInsets().top + getInsets().bottom));
        

        但这总是适用于任何尺寸:

        setSize(width + 14, height + 7);
        

        如果你不想让边框变边框,只想要白色区域,这里:

        setSize(width + 16, height + 39);
        

        这仅适用于 Windows 10,对于 MacOS 用户,请使用@ben 的答案。

        【讨论】:

        • 要使框架在任何显示器上都足够大,应该是:this.setSize(widthofjPanel+ leftInset + rightInset, heightofjPanel+ topInset + bottomInset);在你用 int topInset = this.getInsets().top;等如果由于可用的屏幕尺寸而导致框架太短,并且您使用的是 jScrollPane,请使用 widthOfVerticalScrollbar = (int) jScrollPane1.getVerticalScrollBar().getPreferredSize().getWidth(); 添加滚动条的宽度;跨度>
        • 查看在 Netbeans 中构建 Java Gui 的 mu 指南:philofjava.webstarts.com
        【解决方案6】:

        框架的上边框大小为 30。您可以编写代码以使用 MouseInputAdapter 打印框架上任意点的坐标。您会发现,当光标刚好在框架的上边框下方时,y 坐标不是零,接近 30。因此,如果您给框架 300 * 300 提供尺寸,则可用于将组件放在框架上的尺寸仅为 300 * 270。因此,如果您需要尺寸为 300 * 300,请提供 300 * 330 尺寸框架。

        【讨论】:

          猜你喜欢
          • 2020-09-20
          • 1970-01-01
          • 2022-12-20
          • 1970-01-01
          • 1970-01-01
          • 2012-09-28
          • 2016-11-10
          • 1970-01-01
          • 2014-10-10
          相关资源
          最近更新 更多