1

I am currently reading chapter 12 of Head First Java about making GUIs. They have just mentioned that JFrames are split into center, north, south, east and west. The book then uses the 2 argument add() method to add specified components to a specified region with that JFrame.

I can add a JButton to each of the five regions fine. I can also add my own JPanel to the center region with JButtons all around it. But then when I try to add a JPanel to any region other than center, the JPanel does not appear.

I really have searched all over the web and Stack Overflow for the past hour and I have not come across anything that mentions adding JPanels to any region other than center in a JFrame. So my question is: is it possible to add JPanels to the north, south, east or west regions of a JFrame?

Thanks in advance to anyone that can help me with this.

Here is the code that I've been trying to run with my JPanel in the north region:

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.BorderLayout;

public class StackQ {

    JFrame frame;

    public static void main(String [] args) {

        StackQ gui = new StackQ();
        gui.go();

    }

    public void go() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton button = new JButton("location test");
        JButton button2 = new JButton("location test");
        JButton button3 = new JButton("location test");
        JButton button4 = new JButton("location test");

        myDrawPanel custom = new myDrawPanel();

        frame.getContentPane().add(button, BorderLayout.CENTER);
        frame.getContentPane().add(button2, BorderLayout.EAST);
        frame.getContentPane().add(button3, BorderLayout.WEST);
        frame.getContentPane().add(button4, BorderLayout.SOUTH);

        frame.getContentPane().add(custom, BorderLayout.NORTH);

        frame.setSize(300,300);
        frame.setVisible(true);
    }

}

class myDrawPanel extends JPanel {

    public void paintComponent(Graphics g) {

        int red = (int) (Math.random() * 255);
        int green = (int) (Math.random() * 255);
        int blue = (int) (Math.random() * 255);

        Color random = new Color(red, green, blue);
        g.setColor(random);
        g.fillOval(20,20,100,100);

    }
}
Wes1324
  • 1,077
  • 8
  • 13
  • Try this tutorial https://docs.oracle.com/javase/tutorial/uiswing/ and more specifically https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html – Aubin Jul 24 '16 at 08:48

2 Answers2

2

It could be clearer but this is described in the BorderLayout documentation:

The components are laid out according to their preferred sizes and the constraints of the container's size.... the CENTER component may stretch both horizontally and vertically to fill any space left over.

Put another way, the CENTER component will be stretched (if needed) to fill the application, and any other components need to specify a preferred-size in order to take some of that from the CENTER.

JButton specifies a preferred size by default, based on the contents of the button. JPanel on the other hand does not - its preferred size depends on its contents, and your JPanel doesn't have any contents, therefore its preferred size is zero.

In short, specify a preferred size for your JPanel and the BorderLayout will try to allocate at least that much space for the panel.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • "will try to allocate": so much for a solution – gpasch Jul 24 '16 at 10:05
  • @gpasch well yes; if the `JFrame` isn't wide/tall enough to accommodate every components' preferred size something's gotta give. That's why it's a *preferred* size. As long as the `BorderLayout` component is itself large enough to fit all it's components the preferred sizes will be respected. – dimo414 Jul 24 '16 at 14:11
  • @dimo414, thank you very much for your reply. I first tried using the setSize() method on the JPanel and it still would not show up in the Frame. Then I tried the setPreferredSize() method on the JPanel in question and it appeared in the northern region of the frame! Any ideas why the setSize() method did not work? Also, when you say "your JPanel doesn't have any contents", does the Oval shape that I fill with colour not count as contents in a JPanel? Thanks again! – Wes1324 Jul 24 '16 at 17:40
  • The short answer is preferred size is simply what layout managers use when determining how to lay out components. It's certainly a little confusing, but [this answer](http://stackoverflow.com/q/1783793/113632) goes into more detail. – dimo414 Jul 24 '16 at 20:39
  • As to the contents of your JPanel no, Swing has no idea what you're drawing in the panel nor how much space it takes up. You still have to confgure how you'd like the panel to be laid out and how large it should be. A `JPanel`'s contents are any `Component` objects you [add to the panel](https://docs.oracle.com/javase/8/docs/api/java/awt/Container.html#add-java.awt.Component-), and the panel's layout manager computes its own preferred size based on the preferred sizes of its contents. If it has no contents its default preferred size is zero. – dimo414 Jul 24 '16 at 20:41
  • @dimo414 Great, thank you so much for your help. It is all so much clearer now. – Wes1324 Jul 24 '16 at 21:33
0

Just for any potential future viewers of this post, to get the desired result, I first imported the Dimension class at the very top of my StackQ class (this is needed because the setPreferredSize() method used later on in the go() method accepts an argument of type Dimension):

import java.awt.Dimension;

And then I added this code to the go() method immediately after the instantiation of the myDrawPanel class:

Dimension dims = new Dimension(1366, 200);
custom.setPreferredSize(dims);

I chose 1366 as the width because that's how big my screen is.

Thanks everyone for your help!

Wes1324
  • 1,077
  • 8
  • 13
  • Try leaving the width at zero; since it's a "preferred" size the layout manager will only use the values it needs. As the documentation mentions "*The `NORTH` and `SOUTH` components may be stretched horizontally*" if the `CENTER` component is wider than they need. For `NORTH` and `SOUTH` it's the height that's significant. – dimo414 Jul 25 '16 at 00:45