1

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);
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Dumas45
  • 501
  • 1
  • 10
  • 20
  • 2
    use a layoutManager in the panel – nachokk Jun 18 '13 at 18:48
  • 3
    @dumas45, there is no good reason to use a null layout. Use Swing the way it was designed to be used and use a layout manager. – camickr Jun 18 '13 at 19:10
  • 1
    The problem is, within a layout manager, the parent container has no idea what size to make the child panel, so it gets sized to 0x0 which is a compnent default size – MadProgrammer Jun 18 '13 at 20:39
  • I have found that setPreferredSize method helps and panel becomes visible. if I use `JFrame.setDefaultLookAndFeelDecorated(true);` before creating GUI, I hope that GUI will the same on Linux, Windows and other OS. Doesn't it? – Dumas45 Jun 19 '13 at 04:35

4 Answers4

5

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

nachokk
  • 14,363
  • 4
  • 24
  • 53
3

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();
Davey Chu
  • 2,174
  • 2
  • 14
  • 24
  • I want to use Absolute Positioning in JPanel, like describing there [link]http://docs.oracle.com/javase/tutorial/uiswing/layout/none.html – Dumas45 Jun 18 '13 at 18:53
  • @Dumas45 Then you need to understand what it is you're losing by not using a layout manager – MadProgrammer Jun 18 '13 at 21:16
3

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.

Community
  • 1
  • 1
Azad
  • 5,047
  • 20
  • 38
  • I have no idea why this got two upvotes. This still doesn't not help the OP. The problem is about adding the panel to the NORTH. This solution does not help. This is another reason why a null layout should not be used. Too much manual coding needs to be done and people don't know about all the little problems. The bottom line is that the proper answer should be to use a layout manager. – camickr Jun 18 '13 at 19:08
  • @camickr: I mentioned the solution, but don't you think telling the negative side of his requirement will be helpful? – Azad Jun 18 '13 at 19:18
  • 1
    The problem is p, by default, has a preferred size of 0x0, its simply a matter of luck that the container you added p to is using a layout manager that does not use the preferred size of its child components to determine the layout results - still the same issue that the OP is facing - solves nothing – MadProgrammer Jun 18 '13 at 21:15
  • @MadProgrammer: my mistake, this example was for the button inside the frame not for the panel, thanks I edited it. – Azad Jun 18 '13 at 22:04
  • Actually now I think it's worse – MadProgrammer Jun 18 '13 at 23:30
  • @MadProgrammer: yes it's, but it's OP's requirement for not using any layout manager. – Azad Jun 19 '13 at 00:03
  • If if was the OP's requirement to shoot themselves in the foot, would still be helping them? – MadProgrammer Jun 19 '13 at 00:07
  • Sorry to be such a pain, but the OP has yet to provide reason why they want to use absolute layout and until they can provide a good reason for it, we should do our best to guide them to a solution which won't have them missing a foot when the finish ;) – MadProgrammer Jun 19 '13 at 00:15
  • @MadProgrammer: your welcome, I am always listening to your very good advices,thanks:) – Azad Jun 19 '13 at 00:20
0

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().

PFROLIM
  • 1,194
  • 9
  • 11