21

So I've been programming in java for a semester or so, and I've had this problem a few times and finally got around to asking.

If I make a JFrame and then set the size, like setSize(400,800) for example. The frame is not actually 800 pixels long. From what I can tell it is actually more like 770 (or maybe 769) pixels long. Also, if you set the vertical size very low (below 30), the frame doesn't even show up, only the top window bar from the OS and the frame doesn't get bigger until you go to a value over 30 (so setSize(400,0) looks the same as setSize(400,20)). Why is this, it's not hard to fix but its weird and I'm curious why this is?

If you need more information about anything just ask and I'll get it to you.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
convergedtarkus
  • 697
  • 2
  • 9
  • 19
  • 1
    You should generally **not** have to set the size of a frame. If you do, it is a sign of trouble. Instead, specify a preferred size for the components within the frame (if possible using constructor arguments e.g. `new JTextArea(40,10)`), or otherwise by setting a preferred size on components & adding them to an appropriate layout/constraints. After that, `pack()` the frame & it will become the minimum size needed to display the GUI. – Andrew Thompson Jul 06 '11 at 08:24
  • you can read the answer http://stackoverflow.com/questions/6384702/setsize-v-s-setpreferredsize-and-pack/6384734#6384734 – Suhail Gupta Jul 06 '11 at 10:00
  • @Andrew: What makes setting size of a frame "Troublesome"? – Logan Jul 06 '11 at 10:20
  • 1
    @Logan: If a frame's only component is a 400x400 rendering area, how big does the frame need to be to accommodate it? Let the JRE figure it out with `pack()`. If you have further questions beyond that, I suggest you (search then) ask your own question. There is far more to be mentioned on the topic than can be squeezed into a comment. – Andrew Thompson Jul 06 '11 at 19:01

6 Answers6

24

JFrame SetSize() contains the the Area + Border.

I think you have to set the size of ContentPane of that

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

So I would advise you to use JPanel embedded in a JFrame and you draw on that JPanel. This would minimize your problem.

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();

I am reading this from Javadoc

The JFrame class is slightly incompatible with Frame. Like all other JFC/Swing top-level containers, a JFrame contains a JRootPane as its only child. The content pane provided by the root pane should, as a rule, contain all the non-menu components displayed by the JFrame. This is different from the AWT Frame case. For example, to add a child to an AWT frame you'd write:

frame.add(child);

However using JFrame you need to add the child to the JFrame's content pane instead:

frame.getContentPane().add(child);

Talha Ahmed Khan
  • 15,043
  • 10
  • 42
  • 49
  • please change `jp.setSize( 400, 800 );` to the `jp.setPreferredSize(new Dimension(400, 800));` if you add `JPanel` to the `JFrame` then `jf.getContentPane().add( jp )` is useless, because you call same `JComponents` – mKorbel Jul 06 '11 at 08:54
  • 1
    @mKorbel, I have changed it to `preferredSize`, Thanks for that. But about the second point, I am not adding `JPanel` to `JFrame`, But I am adding the `JPanel` to the `JFrame`'s child `JRootPane`. Please read the comment that I added in the end. – Talha Ahmed Khan Jul 06 '11 at 09:34
  • again that not necessary add any JComponent to the ContentPane in Swing, if you adds JFrame#add(JPanel) that same (with BorderLayout.CENTER) as JFrame.getContentPane().add(JPanel), anyway +1 – mKorbel Jul 06 '11 at 10:15
14

It's probably because size of a frame includes the size of the border.

A Frame is a top-level window with a title and a border. The size of the frame includes any area designated for the border. The dimensions of the border area may be obtained using the getInsets method. Since the border area is included in the overall size of the frame, the border effectively obscures a portion of the frame, constraining the area available for rendering and/or displaying subcomponents to the rectangle which has an upper-left corner location of (insets.left, insets.top), and has a size of width - (insets.left + insets.right) by height - (insets.top + insets.bottom).

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

Kyle
  • 1,978
  • 1
  • 18
  • 30
1

There are lots of good reasons for setting the size of a frame. One is to remember the last size the user set, and restore those settings. I have this code which seems to work for me:

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);
    }
}

}

xpusostomos
  • 1,309
  • 11
  • 15
1

On OS X, you need to take into account existing window decorations. They add 22 pixels to the height. So on a JFrame, you need to tell the program this:

frame.setSize(width, height + 22);
Zizouz212
  • 4,908
  • 5
  • 42
  • 66
ben
  • 11
  • 1
0

I know that this question is about 6+ years old, but the answer by @Kyle doesn't work.

Using this

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

But this always work in any size:

setSize(width + 14, height + 7);

If you don't want the border to border, and only want the white area, here:

setSize(width + 16, height + 39);

Also this only works on Windows 10, for MacOS users, use @ben's answer.

  • 1
    to make the frame big enough on whatever display, it should be: this.setSize(widthofjPanel+ leftInset + rightInset, heightofjPanel+ topInset + bottomInset); after you get the insets with int topInset = this.getInsets().top; etc. if the frame will be too short because of available screen size, and you are using a jScrollPane, add the width of the scrollbar with widthOfVerticalScrollbar = (int) jScrollPane1.getVerticalScrollBar().getPreferredSize().getWidth(); – PiBurner May 09 '18 at 02:44
  • check out mu guide to Java Gui building in Netbeans at: http://philofjava.webstarts.com/ – PiBurner Jul 10 '18 at 18:13
0

The top border of frame is of size 30.You can write code for printing the coordinate of any point on the frame using MouseInputAdapter.You will find when the cursor is just below the top border of the frame the y coordinate is not zero , its close to 30.Hence if you give size to frame 300 * 300 , the size available for putting the components on the frame is only 300 * 270.So if you need to have size 300 * 300 ,give 300 * 330 size of the frame.