2

I have a parent JPanel with a Y_AXIS layout. The children of this container are all JPanels as well. The components are stacking fine, and are all alligned, but i want them to stick to the top of the parent JPanel so all excess space is in the bottom, and there is no extra space between the components. I have tried using glue, but i might be doing something wrong. I have also set the AllignmentX and AllignmentY to left and top respectively on all children.

So, what i want is a stack of children in the parent panel, that is not stretched in height, and sticks to the top (and left, if possible) of the parent container, with all excess space placed in the bottom, as such:

EDIT:

protected void initContent(JPanel panel) {
    id = new JTextField();
    typename = new JTextField();
    currentstep = new JComboBox();
    currentowner = new JComboBox();
    organization = new JTextField();
    area = new JTextField();
    active = new JLabel();
    finished = new JLabel();
    fields = new JList();
    linkedassignments = new JList();
    jobs = new JList();
    JPanel infopanel = new JPanel();
    JPanel listpanel = new JPanel();
    infopanel.setLayout(new BoxLayout(infopanel, BoxLayout.Y_AXIS));
    infopanel.add(Box.createVerticalGlue());
    infopanel.add(makeInfoContainer("Id", id, 50, 100));
    infopanel.add(makeInfoContainer("Type", typename, 50, 100));
    infopanel.add(makeInfoContainer("Organization", organization, 50, 100));
    infopanel.add(makeInfoContainer("Area", area, 50, 100));
    infopanel.add(makeInfoContainer("Active", active, 50, 100));
    infopanel.add(makeInfoContainer("Finished", finished, 50, 100));
    infopanel.add(makeInfoContainer("Step", currentstep, 50, 100));
    infopanel.add(makeInfoContainer("Owner", currentowner, 50, 100));
    listpanel.setLayout(new GridLayout(0,1,5,5));
    listpanel.add(makeJListContainer("Fields", fields, 200, 200));
    listpanel.add(makeJListContainer("Assignments", linkedassignments, 200, 200));
    listpanel.add(makeJListContainer("Jobs", jobs, 200, 200));
    panel.add(infopanel);
    panel.add(listpanel);
}


private Container makeInfoContainer(String name, Component comp, int labelwidth, int compwidth){
    JPanel cont = new JPanel();
    cont.setAlignmentY(Container.TOP_ALIGNMENT);
    cont.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0));
    JLabel lbl = new JLabel(name);
    lbl.setPreferredSize(new Dimension(labelwidth, 25));
    cont.add(lbl);
    comp.setPreferredSize(new Dimension(compwidth, 25));
    cont.add(comp);
    return cont;
}

private Container makeJListContainer(String name, JList list, int areawidth, int areaheight){
    Box cont = new Box(BoxLayout.Y_AXIS);
    cont.setPreferredSize(new Dimension(areawidth, areaheight));
    JLabel label = new JLabel(name);
    cont.add(Box.createHorizontalGlue());
    cont.add(label);
    JScrollPane pane = new JScrollPane();
    pane.setAlignmentY(Component.TOP_ALIGNMENT);
    pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    pane.add(jobs);
    cont.add(pane);
    return cont;
}

Window resulting from code

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Martin Nielsen
  • 1,865
  • 6
  • 30
  • 54
  • You can, upload images and/or sample code, which would really help. I'd take a look at some of the other layout managers, I don't think it will do what you want – MadProgrammer Jul 28 '12 at 08:05
  • make sure the children all implement getMaximumSize() with something reasonable reasonable: BoxLayout will never size them larger than that – kleopatra Jul 28 '12 at 08:48

2 Answers2

4

Assuming that the layoutManager of the containing panel (that is the one passed into the initContent) has a horizontalBoxLayout

  • remove all the glue stuff
  • set the alignmentY of both info/listPanel to top
  • implement the getMaximum of the infoPanel to return its pref

Something like (borders are just to visualize which container is where, often hard to decide with so much nesting :)

JComponent panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.setBorder(BorderFactory.createLineBorder(Color.GREEN));
initContent(panel);

// in initContent
JPanel infopanel = new JPanel() {

    @Override
    public Dimension getMaximumSize() {
        return getPreferredSize();
    }


};
infopanel.setBorder(BorderFactory.createLineBorder(Color.RED));
infopanel.setAlignmentY(0f);
infopanel.setLayout(new BoxLayout(infopanel, BoxLayout.Y_AXIS));
JPanel listpanel = new JPanel();
listpanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
listpanel.setAlignmentY(0f);
listpanel.setLayout(new GridLayout(0,1,5,5));

While you are at it: remove all setXXSize - hard-coding sizes is wrong, some reasons.

Community
  • 1
  • 1
kleopatra
  • 51,061
  • 28
  • 99
  • 211
  • Brilliant idea. The borders showed that the problem is not the inner panel. But the outer panel being passed to the method. – Martin Nielsen Jul 28 '12 at 11:05
1

Try removing the glue at the top of the container and add it to the bottom instead.

Changed code:

protected void initContent(JPanel panel) {
       [...]
       JPanel infopanel = new JPanel();
       JPanel listpanel = new JPanel();
       infopanel.setLayout(new BoxLayout(infopanel, BoxLayout.Y_AXIS));
       infopanel.add(Box.createVerticalGlue());
       infopanel.add(makeInfoContainer("Id", id, 50, 100));
       [...]
       infopanel.add(makeInfoContainer("Owner", currentowner, 50, 100));
       infopanel.add(Box.createVerticalGlue());
       listpanel.setLayout(new GridLayout(0,1,5,5));
       [...]
}
Kasper van den Berg
  • 8,951
  • 4
  • 48
  • 70