Search code examples
javaswinguser-interfacelayout-managergridbaglayout

How to keep JPanel at top of parent container at runtime?


I create a parent container onto which I place several JPanel objects, each containing several JButton objects.

I create the parent panel, add the GridBagConstraints then add each child panel to the parent:

final JPanel options = new JPanel(new GridBagLayout());
        options.setBorder(new TitledBorder("Select Option"));
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        gbc.anchor = GridBagConstraints.NORTH;

        options.add(findPanel, gbc);
        options.add(addPanel, gbc);
        options.add(changePanel, gbc);
        options.add(dropPanel, gbc);
        gbc.weighty = 1.0;
        options.add(new JPanel(), gbc);

With options.add(new JPanel(), gbc); used to take up the extra space under my wanted panels. Works great....until I want to change the contents of the parent after user interaction:

partnoFai.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent ae){
                    options.remove(findPanel);
                    options.remove(addPanel);
                    options.remove(changePanel);
                    options.remove(dropPanel);
                    options.add(partnoFaiInp, gbc);
                    gbc.weighty = 1.0;
                    options.add(new JPanel(), gbc);
                    frame.pack();
                    frame.validate();
                } 
            } );

It's adding the new panel, options.add(partnoFaiInp, gbc); to the middle of the parent when I want it at the top. Why wouldn't gbc.anchor = GridBagConstraint.NORTH; keep the new panel in the NORTH of the panel?

Any help is appreciated.


Solution

  • You have to think of the Container in terms of a stack

    When you first setup the panel using...

    options.add(findPanel, gbc);
    options.add(addPanel, gbc);
    options.add(changePanel, gbc);
    options.add(dropPanel, gbc);
    gbc.weighty = 1.0;
    options.add(new JPanel(), gbc);
    

    The container has a list of components looking like {findPanel, addPanel, changePanel, dropPanel, JPanel}

    When you remove the components using something like...

    options.remove(findPanel);
    options.remove(addPanel);
    options.remove(changePanel);
    options.remove(dropPanel);
    

    The container now has a list of components looking like {JPanel}

    Then when you add your new component using...

    options.add(partnoFaiInp, gbc);
    gbc.weighty = 1.0;
    options.add(new JPanel(), gbc);
    

    The container now has a list of components looking like {JPanel, partnoFaiInp, JPanel}

    So, instead of adding the another "filler" component, you could just specify the insert point of the panel when you add it...

    options.add(partnoFaiInp, gbc, 0);
    frame.pack();
    frame.validate();
    

    The container now has a list of components looking like {partnoFaiInp, JPanel}