A lot comes down to the requirements of the content and the layout manager. Rather then looking "how big" you'd like the frame to be, focus on the amount of space the content needs. The frame will then "pack" around this.
This means that the frame will "content size + frame border size" big.
JFrame#pack
takes into consideration the content's preferred size and adds in the frames border insets automatically.
So, the only thing you need to is call JFrame#pack
AFTER you finished adding the content to it
So, based on your code:
public class Testing {
public static void main(String[] args) {
JFrame frame = new JFrame("hi");
for (int i = 0; i < 10; i++) {
JButton a = new JButton();
a.setSize(20,20);
a.setLocation(20*i, 0);
frame.getContentPane().add(a);
}
frame.setLayout(null);
frame.pack();
frame.setVisible(true);
}
}
You are using a null
layout. JFrame#pack
will use the information provided by the layout manager to determine the "preferred" size of the overall content.
Avoid using null
layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify.
Rather the focusing on the absolute, which would be variable between OS's (and even different PC's with the same OS), focus on the user experience.
As has, already, been demonstrated, you can easily get this to work using a GridLayout

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(10, 10, 0, 0));
for (int index = 0; index < 10 * 10; index++) {
JButton btn = new JButton(String.valueOf(index)) {
@Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
};
add(btn);
}
}
}
}
If, you need a more complex management (ie depth by breadth), you could use a GridBagLayout
instead
Take a look at Laying Out Components Within a Container, How to Use GridLayout and How to Use GridBagLayout for more details ;)