I'm trying to make a collapsible panel look and having some issue with the layout manager, I'm pretty new at using layout managers and trying to userstand them. I have Jpanel with a flowlayout, I'm adding additional Jpanels which uses a GridBagLayout that removes and adds components with the click of a button, to give collapsed look to give it a form feel, I want the collapsible pane to stretch across the whole frame when I remove all the components but I get the following result
to look like this
which I achieved by adding a blank JLabel. This is working fine until I started adding more Jpanels that are not stretching across the screen like I want, like the Hardware Bundle Jpanel below.
not 100% sure but I believe this is an issues with the Flow layout manager just doing its job and just adding the components to the frame, just didn't know if there is something I can do do get my collapse Jpanel to fill the frame horizontally.
Any help is appreciated
Here is my Jpanel class that uses the flowlayout and manages my background
public class Panel extends JPanel {
private final ArrayList<Component> comp = new ArrayList();
public Panel() {
super();
this.setLayout(new FlowLayout(FlowLayout.LEFT));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponents(g);
g.drawImage(Assets.getImage(Assets.background, 350, 590), 0, 0, this);
}
public void addComp(Component c) {
this.add(c);
comp.add(c);
}
public void createCopy(){
Button copy = new Button("Process", new ImageIcon(Assets.getImage(Assets.button, 120, 35)));
copy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(Component c : comp){
System.out.println(((CollapsePane)c).format());
}
}
});
add(copy);
}
}
here is my abstract class that manages the remove and adding of my form componenets
abstract class CollapsePane extends JPanel {
private JButton expand;
private JLabel fill = new JLabel(" ");
private boolean collapse = false;
public GridBagConstraints c;
private ArrayList<Pair> comp = new ArrayList();
String title;
public CollapsePane(String title) {
this.setOpaque(false);
this.title = title;
TitledBorder border;
border = BorderFactory.createTitledBorder(new BevelBorder(BevelBorder.RAISED, Color.black, Color.black), title);
border.setTitleJustification(TitledBorder.LEFT);
this.setBorder(border);
this.setLayout(new GridBagLayout());
c = new GridBagConstraints();
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
createButton();
this.add(expand, c);
}
public CollapsePane(String title, boolean collapse) {
this.title = title;
this.setOpaque(false);
TitledBorder border;
border = BorderFactory.createTitledBorder(new BevelBorder(BevelBorder.RAISED, Color.black, Color.black), title);
border.setTitleJustification(TitledBorder.LEFT);
this.setBorder(border);
this.collapse = collapse;
this.setLayout(new GridBagLayout());
c = new GridBagConstraints();
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
createButton();
this.add(expand, c);
this.collapse = collapse;
}
abstract void config();
private void createButton() {
if (collapse == false) {
expand = new Button("-", new ImageIcon(Assets.getImage(Assets.blankButton, 30, 30)));
} else {
expand = new Button("+" , new ImageIcon(Assets.getImage(Assets.blankButton, 30, 30)));
}
expand.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (collapse) {
expand.setText("-");
remove(fill);
collapse = false;
add();
} else {
expand.setText("+");
clear();
add(fill);
collapse = true;
}
}
});
}
private void clear() {
System.out.println("clear");
for (Pair p : comp) {
this.remove((Component)p.getComponent());
}
}
public void add() {
//System.out.println("add");
//System.out.println("compt size:" + comp.size());
for (int i = 0; i < comp.size(); i++) {
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.WEST;
c.insets = new Insets(0, 5, 5, 5);
c.gridx = (int)comp.get(i).getxPos();
c.gridy = (int)comp.get(i).getyPos();
// System.out.println("coor " + i + " " + x + " " + y);
this.add((Component)comp.get(i).getComponent(), c);
}
}
public void addComp(Component comp, int x, int y) {
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.WEST;
c.insets = new Insets(0, 5, 5, 5);
c.gridx = x;
c.gridy = y;
if (!collapse) {
this.add(comp, c);
}
this.comp.add(new Pair(comp,x,y));
}
Like most things, this is all about illusion. You also need to take into consideration each individual container and how they are getting laid out and how that might effect how the parent's get laid out.
In the following example, the "contents" of the collapsed pane
fillhorizontally, but also occupy all the available horizontal space (ieweightx = 1), this ensures that the control is positioned to the "first start line" (ie top/left).However, when the "contents" are hidden (ie collapsed), the control button will become the only component used to determine the layout, meaning that it will shift to the middle of the container. Even if you layout of the container to occupy the horizontal area. This is perfectly normal.
To over come this, I added a "filler" component that will, when the container is collapsed, occupy the remaining horizontal space instead (ie
weightx = 1), there by forcing the control button to remain at the left side ... "magic"You will also note that I add a empty
JPanelbelow the the two collapsed panes and force it to occupy the remaining vertical space, this ensures that the layout stays at the top of the container.