Dynamically growing JPanel with BoxLayout (on a null layout)

独自空忆成欢 提交于 2019-12-19 12:07:21

问题


I have a JPanel with a vertical BoxLayout on top of a JPanel with a null layout.

I would like the JPanel with the BoxLayout to grow as the components are being added.

See this code:

public static void main (String[] args) {
    JFrame f = new JFrame();
    f.setSize(500,500);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel total = new JPanel();
    total.setLayout(null);
    total.setSize(f.getWidth(),f.getHeight());
    total.setBackground(Color.green);
    JPanel box = new JPanel();
    box.setLocation(100,200);
    box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
    box.add(new JButton("test"));
    box.add(new JLabel("hey"));
    total.add(box);
    f.add(total);
    f.setVisible(true);
}

You will notice that no components show up.

How can I make the JPanel "box" such that the size dynamically increases as I add more components (which are added vertically).

IN ADVANCE: I need the position of "box" to be at exactly 100,200 so please do not suggest that I do not use null layout. I must use null layout. The null layout of "total" should not effect the answer to my question, which focuses on the "box" panel.


回答1:


By throwing away the layout manager, you suddenly become responsible for it's job. A job I might add, which isn't easy ...

Basically, given you example, you've failed to set the size of the child component...

JFrame f = new JFrame();
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel total = new JPanel();
total.setLayout(null);
total.setSize(f.getWidth(), f.getHeight());
total.setBackground(Color.green);

JPanel box = new JPanel();
box.setLocation(100, 200);
box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
box.add(new JButton("test"));
box.add(new JLabel("hey"));
box.setSize(100, 100);  // <-- Don't forget this..

total.add(box);
f.add(total);
f.setVisible(true);

Personally, I think your asking for trouble, but what would I know...

A better idea might be to use something like an EmptyBorder to providing padding...

JFrame f = new JFrame();
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel total = new JPanel(new BorderLayout());
total.setSize(f.getWidth(), f.getHeight());
total.setBackground(Color.green);
total.setBorder(new EmptyBorder(100, 200, 100, 200));

JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
box.add(new JButton("test"));
box.add(new JLabel("hey"));

total.add(box);
f.add(total);
f.setVisible(true);

Updated with Layout Manager example

Now, if all the layout managers are failing you, you could try writing your own. This has the benefits you need from the null layout manager and the benefits of intergrating into Swing's component changing process, without the need to resort to ComponentListeners and ContainerListeners

JPanel total = new JPanel();
total.setLayout(new SuperAwesomeBetterThenYoursLayout());

Custom Layout Manager

public static class SuperAwesomeBetterThenYoursLayout implements LayoutManager {

    @Override
    public void addLayoutComponent(String name, Component comp) {
    }

    @Override
    public void removeLayoutComponent(Component comp) {
    }

    @Override
    public Dimension preferredLayoutSize(Container parent) {
        return new Dimension(100, 300);
    }

    @Override
    public Dimension minimumLayoutSize(Container parent) {
        return new Dimension(100, 300);
    }

    @Override
    public void layoutContainer(Container parent) {
        boolean laidOut = false;
        for (Component child : parent.getComponents()) {
            if (child.isVisible() && !laidOut) {
                child.setLocation(200, 100);
                child.setSize(child.getPreferredSize());
            } else {
                child.setSize(0, 0);
            }
        }
    }

}

This basically represents the work you are going have to do anyway, but does in away that works with how Swing was designed...




回答2:


Suggestions:

  • Don't use null layout, almost ever.
  • Why not give the total JPanel a BorderLayout?
  • Then add the BoxLayout using JPanel to the BorderLayout.NORTH (or also known as BorderLayout.PAGE_START) position.

Edit
You state,

IN ADVANCE: I need the position of "box" to be at exactly 100,200 so please do not suggest that I do not use null layout. I must use null layout. The null layout of "total" should not effect the answer to my question, which focuses on the "box" panel.

I think that you are once again putting needless restrictions on your program. You can place your "box" at 100, 200 easily by putting an empty border of that size around it, or by other means. But the answer is not to throw out use of the null layout.




回答3:


Off the bat, what I would change:

public static void main (String[] args) {
    JFrame f = new JFrame();
    //f.setSize(500,500);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel total = new JPanel();
    //total.setLayout(null); //<-- this is usually a bad idea, but you can keep it
    //                                if you want to specify an EXACT location
    //                                for your JPanel
    total.setPreferredSize(500, 500);
    total.setBackground(Color.green);
    JPanel box = new JPanel();
    //box.setLocation(100,200);
    box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
    box.add(new JButton("test"));
    box.add(new JLabel("hey"));
    total.add(box);
    f.add(total);
    f.pack();
    f.setVisible(true);
}

Once you have that basis, all you need to do to dynamically change the size of a JPanel is:

panel.setSize(width, heightOfComponentWithin * numberOfComponents);
container.repaint(); //<-- Im not sure if you also have to call panel.repaint(),
//                           you probably don't have to.

I would also recommend using a scroll view, just in case the JPanel starts getting out of view. Good Luck!




回答4:


Maybe it's because you haven't setSize for box JPanel.



来源:https://stackoverflow.com/questions/14290020/dynamically-growing-jpanel-with-boxlayout-on-a-null-layout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!