What your after I think, is the gridbag layout manager.
There is a big conceptual leap between the simple and the advanced layout managers. If you can use the standard managers they are usually easier but once they arent good enough your pretty much forced to use gridbag, its the most complicated and at times its very very hard to use. You can set a null layout and then just position things with pixels positions, but it usually wont do becuase its not dynamic and you dont get full control over things, and then of course small differences between peoples different look and feels (as in default windows mac and unix) will throw off calculations, so really its better for components to be postioned relative to each other.
If you search it up im sure you will find plentifull amounts of examples and tutorials, here is a quick reference of it in practice, the mainframe constructor for my poker game which pretty much uses gridbag everywhere.
I have found that once I know the manager its the most capable and predictable so ive just begun to use it everywhere.
...
//Layout Variables//
private GridBagLayout _FrameLayout;
private GridBagConstraints _FrameLayoutConstraints;
//Panel Variables//
protected CardsPanel _playerOneCardPanel;
protected CheckPanel _playerOneCheckPanel;
protected CardsPanel _playerTwoCardPanel;
protected CheckPanel _playerTwoCheckPanel;
protected ButtonPanel _buttonPanel;
//Game Logic Object//
protected Logic _logic;
protected Container _c;
...
//MainFrame Constructor//
public MainFrame()
{
setTitle("Waylander's Vs Poker");
setLocation(100,100);
setSize(660,380);
setResizable(false);
addWindowListener(new MyWindowListener());
_FrameLayout = new GridBagLayout();
_FrameLayoutConstraints = new GridBagConstraints();
_c = getContentPane();
_c.setLayout(_FrameLayout);
_FrameLayoutConstraints.fill = GridBagConstraints.HORIZONTAL;
_FrameLayoutConstraints.gridy = 0;
_FrameLayoutConstraints.insets = new Insets(10,0,0,0);
addComponent(_playerOneCardPanel = new CardsPanel());
_FrameLayoutConstraints.gridy = 1;
_FrameLayoutConstraints.insets = new Insets(0,0,0,0);
addComponent(_playerOneCheckPanel = new CheckPanel());
_FrameLayoutConstraints.gridy = 2;
_FrameLayoutConstraints.insets = new Insets(15,0,0,0);
addComponent(_playerTwoCardPanel = new CardsPanel());
_FrameLayoutConstraints.gridy = 3;
_FrameLayoutConstraints.insets = new Insets(0,0,0,0);
addComponent(_playerTwoCheckPanel = new CheckPanel());
_FrameLayoutConstraints.gridy = 4;
_FrameLayoutConstraints.insets = new Insets(15,0,0,0);
addComponent(_buttonPanel = new ButtonPanel());
_logic = new Logic();
setVisible(true);
}
//Apply constraints and add components
protected void addComponent(Component component)
{
_FrameLayout.setConstraints( component, _FrameLayoutConstraints);
_c.add(component);
}
Basically you define a constraints object, which has many properties I think around 20 the ones I dont set I know what the defaults are and havent bothered setting them.
Once you define the constraints for the component you apply the constraints to it and then add it to the container. You use the same constraints object each time so you have to set things back after you use them, the complications come from knowing what each property does and whats even more complicated is how they react with each other.
Waylander.