Question

Colleagues.

I'm trying to construct simple GUI in Java, where JFrame has Border Layout. I want to put JScrollPane with JTable to CENTER, and JPanel without layout to NORTH.

The problem is that JPanel doesn't visible. There is simple examle of the problem:

JFrame frame = new JFrame("Test frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JButton button = new JButton("Test button");
button.setBounds(10, 10, 40, 20);

JPanel panelN = new JPanel(null); // layout = null, panelN without layout
panelN.add(button);
frame.add(panelN, BorderLayout.NORTH);

JTable table = new JTable(new DefaultTableModel(4, 4));
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane, BorderLayout.CENTER);

frame.setSize(400, 400);
frame.setVisible(true);
Was it helpful?

Solution

You have to use a LayoutManager. It's totally discouraged not using layoutManager, but if you want this you have to set panel.setBounds(..) to the panel too.

By default JPanel has FlowLayout so if you put

JPanel panelN = new JPanel(); // FlowLayout used 
panelN.add(button);
frame.add(panelN, BorderLayout.NORTH);

So your frame will look like this.

example

Layout Managers determines the size and position of the components within a container. Although components can provide size and alignment hints, a container's layout manager has the final say on the size and position of the components within the container.

It's strongly recommended cause for example if you have to resizes components or show in differentes resolutions you delegate this work to layout managers

OTHER TIPS

I don't know the expected behavior of a null layout, but without further requirements you might as well just instantiate with the zero-arg constructor:

new JPanel();

If you didn't set any layout to the panel, when adding components the panel don't know where to put the component, so baisicly the component don't show until you set a specific location for components one by one by component.setBounds(x,y,width,hieght) method.

Note that it's not a good practice to remove the layout manager because of the different platformes, suppose that your program working on Window and MacOS and Linux, you'v better to use the layout managers instead.

Take a look at this post also and see @Andrew Thompson's comment on my answer:

Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components. For a robust GUI, instead use layout managers, or combinations of them, along with layout padding & borders for white space, to organize the components.

After all: If you have a requirement or an assignment telling you you must use absolute layout, then use it, otherwise avoid it.

It is OK to use containers with no layout manager because you actually CAN set container's layout to NULL. And it's a nice idea to position your components with setBounds(). But in this case, you just have to consider your container. What size it need to be? A layout manager would calculate this for you, and if you don't have one, you have to set the size of your panel by yourself, according to components you have added to it.

As pointed by others here, the case it that the border-layout manager of your frame needs the preferred size of your NORTH panel (actually, the preferred height). And you have to set it, or values will be zeros and the container will become invisible. Note that for the CENTER panel this is not needed as it gets all space possible.

I had a problem like yours before and have written a fast function to resize a container according to bounds of a given component. It will be as large as needed to show this component, so dimension (w,h) and position (x,y) are considered. There's an "auto-resize" version that can be used once, after all components are added.

public static void updatePreferredSize(Container cont, Component comp) {

    int w = cont.getPreferredSize().width;
    int h = cont.getPreferredSize().height;

    int W = comp.getBounds().x + comp.getBounds().width;
    int H = comp.getBounds().y + comp.getBounds().height;

    if (W>w||H>h) cont.setPreferredSize(new Dimension(W>w?W:w, H>h?H:h));
}

public static void autoPreferredSize(Container cont) {

    for (Component comp : cont.getComponents())
        updatePreferredSize(cont, comp);
}

You can use updatePreferredSize() after adding every component to a panel, or use autoPreferredSize() once, after all addings.

// [...]
panelN.add(button);
updatePreferredSize(panelN, button);
// [...]

// or...

// [...]
autoPreferredSize(panelN);
// [...]
frame.setVisible(true);

This way, if you do not set you north panel height with a fixed value, with help of these functions you can expect your button will be visible according the position you set it with setBounds().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top