I have a JPanel parent with 3 JPanel children inside. They all currently make use of GridLayout and together represent a UML class. Problem is that when I add a new attribute or method, all 3 JPanel grow to the same size.
Desire behaviour is that:
- The title box's size always remain the same whenever a method or attribute is added.
- When a method is added, only the method panel grows and title and attribute panel's size stay the same.
- When an attribute is added, only the attribute panel grows and other panels size stay the same.
The parent JPanel already can automatically grow/shrink whenever a method/attribute is added. I'm toying around with GridBagLayout atm but I'm getting nowhere near the desire results.
Is there a simple (or simpler) way for me to solve this?!
Here is few pics to show my situation.
A newly created UML class =>
this is how it currently behaves =>
But I want this => or this=>
or this =>
Edit2: added new pics for clarity. Im terribly sorry if original version was misleading.
Edit3: YESS! I have sorted it! Felt like forever!! Here is the SSEEC:
Child panel
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.MouseInputAdapter;
import javax.swing.event.MouseInputListener;
public class APanel extends JPanel{
private JTextField tf;
public APanel() {
this.setLayout(new GridLayout(0,1));
this.addMouseListener(mouseInputListener);
}
MouseInputListener mouseInputListener = new MouseInputAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("Adding a new text field!");
tf = MyTF.create("Double click");
addNewTF(tf);
Component source = (Component) e.getSource();
Container c = source.getParent();
while(true) {
if(c instanceof PPanel)
break;
else
c=c.getParent();
}
PPanel p = (PPanel) c;
p.expand();
}
};
public void addNewTF(JTextField tf) {
this.add(tf);
this.setSize(this.getWidth(), this.getHeight()+tf.getHeight());
this.revalidate();
this.repaint();
}
}
Parent panel:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class PPanel extends JPanel{
//private APanel panel1;
private JPanel panel1;
private APanel panel2;
private APanel panel3;
public PPanel() {
this.setLayout(new BoxLayout(this , BoxLayout.Y_AXIS));
this.setBackground(Color.black);
panel1 = new JPanel();
panel1.setLayout(new GridLayout(0,1));
panel1.add(new JTextField("title"));
panel2 = new APanel();
panel2.setBorder(BorderFactory.createLineBorder(Color.red));
panel3 = new APanel();
panel3.setBorder(BorderFactory.createLineBorder(Color.black));
this.add(panel1);
this.add(Box.createRigidArea(new Dimension(0,1)));
this.add(panel2);
this.add(panel3);
}
public void expand() {
this.setSize(this.getWidth(), this.getHeight()+33);
this.revalidate();
this.repaint();
}
public static void main(String[] args) {
JFrame frame = new JFrame();
PPanel panel = new PPanel();
panel.setBounds(10, 10, 100, 150);
JPanel c = new JPanel(null);
c.add(panel);
frame.add(c);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(350, 300));
frame.setTitle("Demo");
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
A helping class:
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import javax.swing.JTextField;
import javax.swing.event.MouseInputAdapter;
import javax.swing.event.MouseInputListener;
public class MyTF {
public static JTextField create(String name) {
final JTextField tf = new JTextField(name);
System.out.println(tf.getPreferredSize());
tf.setPreferredSize(new Dimension(100,33));
tf.addMouseListener(mouseInputListener);
return tf;
}
static MouseInputListener mouseInputListener = new MouseInputAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Component source = (Component) e.getSource();
Container c = source.getParent();
while(true) {
if(c instanceof PPanel)
break;
else if(c instanceof APanel)
{
c.dispatchEvent(e);
c = c.getParent();
break;
}
else
c=c.getParent();
}
c.dispatchEvent(e);
}
};
}
I gave up the efford playing with GridBagLayout, it was just too much for me. Then I tried borderLayout as suggested but couldn't get it to work like I want it either. Then finally BoxLayout, it should had worked but there was a bug in my code! So when I tried out 0verbose code suggest and playing around with it, it failed! Not until, I finished up the SSEEC, did the final compile and run it before I decided to post (I practically gave up at this point) then I realised that it worked...The panel that can grow in their own space, they dont interfere with each other.
I was like WTF!
Went back to my code and compared it SSEEC and there was a bug, the code to expand the height of the panel was in wrong place so they sort of like eating into each other spaces.
Better yet! I can specify the distance between the middle box with the box above and below it by one pixel. That means I can still use the trick by mKorbel to draw the back line seperating those boxes!
Edit 4: is there a way for me to set size of a component? If you run the SSEEC, you will notice that once the JTextField is added in, it's huge! It's bigger than the container...