Why does the JFrame setSize() method not set the size correctly?
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 n开发者_高级运维eed more information about anything just ask and I'll get it to you.
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 withFrame
. Like all other JFC/Swing top-level containers, a JFrame contains aJRootPane
as its only child. The content pane provided by the root pane should, as a rule, contain all the non-menu components displayed by theJFrame
. 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 theJFrame
's content pane instead:
frame.getContentPane().add(child);
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
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);
}
}
}
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);
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.
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.
精彩评论