set custom location for a component in box layout

2019-08-14 13:09发布

问题:

I have a frame, inside this frame I have a panel with box layout, inside this panel I have 4 more panels.

        mainFrame = new JFrame("Basket Game");
        mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

        mainPanel.add(options);
        mainPanel.add(pname);
        mainPanel.add(info);
        mainPanel.add(gamearea);    

    mainFrame.setContentPane(mainPanel);
    mainFrame.pack();
    mainFrame.getContentPane().setBackground(Color.LIGHT_GRAY);
    mainFrame.setResizable(false);
    mainFrame.setVisible(true);
    mainFrame.setSize(600,600);

The form looks like this:

The first 3 panel is ok for me. But for the last panel (black one) I want to add some components with custom coordinates. But when I try to add them with custom coordinates:

basket.setLocation(500, 500);
gamearea.add(basket);

It goes directly top-center of the panel (coordinates doesn't affect it's location)

When I set gameareIs layout to null I can't see my label on the panel. I think I should do something extra for it. How can I do that?

回答1:

The problem is not with your layout manager (null), nor with anything being left out. The problem is simply 500x500 is outside of the bounds of game area.

public class NullLayout {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(NullLayout::new);
    }

    NullLayout() {
        JFrame frame = new JFrame("Basket Game");
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

        for (int i = 0; i < 4; i++) {
            JPanel strip = new JPanel();
            strip.setMaximumSize(new Dimension(Integer.MAX_VALUE, 50));
            strip.setBorder(BorderFactory.createTitledBorder("Strip " + i));
            strip.add(new JLabel("Strip " + i));
            mainPanel.add(strip);
        }

        JPanel gamearea = new JPanel();
        gamearea.setLayout(null);
        mainPanel.add(gamearea);

        for (int i = 0; i < 5; i++) {
            int x = i * 100, y = i * 100;
            JPanel basket = new JPanel();
            basket.setSize(200, 50);
            basket.setLocation(x, y);
            basket.setBackground(Color.YELLOW);
            basket.add(new JLabel("x = " + x + ", y = " + y));
            gamearea.add(basket);
        }

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(mainPanel);
        frame.pack();
        frame.setResizable(false);
        frame.setSize(600, 600);

        frame.setVisible(true);
    }
}

Notice that the Basket at 400,400 is not showing; it would be off the bottom of the game area.



回答2:

It is almost always wrong to use a null layout. You should use a LayoutManager that helps place the components where you want them - especially useful if the user alters the size of the main frame. Use a GridBag or Mig layout.

If you absolutely insist on using a null layout, create a new GameArea class that extends JPanel, override its paintComponent() method and set the children's positions using child.setBounds(...). Be sure the first statement in your overridden method is super.paintComponent(g); .