Swing ContainersJ8 Home « Swing Containers

In this lesson we look at the javax.swing.JFrame top-level container class, adding depth to frames using panes and the javax.swing.JPanel background container class.

Nearly all the Swing components we need to create our own GUI applications: buttons, check-boxes, text fields etc., extend from the javax.swing.JComponent class, the exceptions being top-level containers such as javax.swing.JDialog and javax.swing.JFrame which are derived from their older AWT counterparts. Aside from top-level containers any Swing component can be placed into another Swing component although common sense and usability preclude us for example, from putting another component within a button. In fact to use a component that inherits from the jComponent class you must place the component in a containment hierarchy whose root is a top-level Swing container such as JDialog or JFrame. In essence this is what GUI applications consist of, containers which we can think of as background components that contain related interactive components which a user can work with. This doesn't preclude user interaction with the background components but the abstraction should help in visualising the structure.

So we construct our GUI applications by placing components within containers and to get everything to work all the components must fit into a top-level container. For our purposes we will be using the javax.swing.JFrame and javax.swing.JPanel objects as our background component of choice to group our interactive components together whilst also taking a look at depth using panes. The layout of the panels within our dialogs and frames and the components within our panels is controlled by Java objects known as layout managers and we will go into much more detail about these objects in the Layout Managers lesson. For now its enough to know that a component that contains other components has a layout manager that controls the size and positioning of the components within it.

The javax.swing.JFrame Class Top

We saw some code in the last lesson where we created a window using the javax.swing.JFrame class and in this section we will take a much closer look at this top-level container. In that example we used javax.swing.JFrame object to create our window but we can also extend from the JFrame class so we inherit the behaviour our class needs to function as a frame. When creating our own frames there are several actions we need to perform on frame creation:

  1. Call a constructor method of the JFrame class using the new operator or super if we have subclassed JFrame.
  2. Set up the title of the frame.
    You set the title up when calling the constructor or by using the setTitle() method that is inherited from java.awt.Frame.
  3. Setup the size of the frame.
    The size of the frame can be set by using the setBounds() and pack() methods that are inherited from java.awt.Windows or one of the setSize() methods that are inherited from java.awt.Component.
  4. Define an action for when the frame is closed by the user pressing the exit button.
    • setDefaultCloseOperation(DISPOSE_ON_CLOSE) - Hide and dispose of the frame but keep running the application.
    • setDefaultCloseOperation(DO_NOTHING_ON_CLOSE) - Keep the frame open and do nothing.
    • setDefaultCloseOperation(EXIT_ON_CLOSE) - Exit program when the exit button is clicked using the System exit method.
    • setDefaultCloseOperation(HIDE_ON_CLOSE) - Hide the frame and continue running the application.
  5. Make the frame visible if this is a requirement when starting up the application.
    This can be achieved using the setVisible() method that is inherited from java.awt.Component.

Lets take a look at an example of extending the JFrame class.


package info.java8;
import javax.swing.JFrame; // An interactive window

public class SubFrame extends JFrame {
    // Construct the frame 
    public SubFrame() {
        super("Extending JFrame");
        setBounds(300, 200, 568, 218);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main (String[] args) {
        SubFrame sf = new SubFrame();   
    }
}

The following screenshot shows the results of compiling and running the SubFrame class on my Windows 7 system. The screenshot is of the far right and top part of my display which has a resolution of 1920 x 1080. If you have a lower resolution you might have to adjust the first parameter of the setBounds() method to see the frame.

run SubFrame class

In the SubFrame() constructor we are calling the JFrame superconstructor that takes a string and passing it a name for our frame. The four parameters we are passing to the setBounds() method correspond to the x-axis, y-axis, width and height of the frame respectively. The x-axis and y-axis are offsets from the top left corner of the displayable window and the width and height set the size of the frame. All measurements are in pixels and so the actual positioning will vary dependant upon the screen size and resolution of the monitor used. We are also asking for the frame to be closed and the application ended by using setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE). The last thing we do is make the frame visible using the setVisible() method. The following diagram should help to clarify the parameters used in the setBounds() method.

Set bounds diagram

Centering a JFrame Top

So far we have just used the Swing library, which offers us lightweight components to use when creating our GUIs. The AWT library also comes with many useful classes to use in conjunction with Swing to make GUI creation a simpler process. The following example shows how we can use the Dimension and Toolkit classes from the AWT library to center a frame on the screen.


package info.java8;
import java.awt.Dimension; // Component dimensions
import java.awt.Toolkit; // The toolkit
import javax.swing.JFrame;

public class CenterFrame extends JFrame {
    // Construct the frame 
    public CenterFrame() {
        super("Centering a JFrame");
        Toolkit awt = this.getToolkit(); // Get toolkit
        this.setSize(new Dimension(568, 218)); // Use Dimension to set our frame size
        Dimension scrnsize = awt.getScreenSize(); // Get monitor screen size
        int x = (int) ((scrnsize.getWidth() - this.getWidth()) / 2); // Get width start position
        int y = (int) ((scrnsize.getHeight() - this.getHeight()) / 2); // Get height start position
        
        setBounds(x, y, 568, 218);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main (String[] args) {
        CenterFrame cf = new CenterFrame();   
    }
}

Try compiling and running the CenterFrame class on your system and regardless of screensize the frame should be centered in the middle of the screen as shown in the screenshot below. This isn't the only way to center a frame on the screen, there are other ways available in the AWT such as using the GraphicEnvironment object, which can be investigated via the Java API documentation.

Center Frame

Sizing a JFrame Top

We can also automate the frame size using the Dimension and Toolkit classes from the AWT library to calculate the size from our monitor screen size. In the example below we set the frame size to half of the monitor's screen size and center it in the middle of the screen.


package info.java8;
import java.awt.Dimension; // Component dimensions
import java.awt.Toolkit; // The toolkit
import javax.swing.JFrame;

public class SizeFrame extends JFrame {
    // Construct the frame 
    public SizeFrame() {
        super("Sizing a JFrame");
        Toolkit awt = this.getToolkit(); // Get toolkit
        Dimension scrnsize = awt.getScreenSize(); // Get monitor screen size
        int a = (int) (scrnsize.getWidth() / 2); // Half monitor width
        int b = (int) (scrnsize.getHeight() / 2); // Half monitor height
        this.setSize(new Dimension(a, b)); // Use Dimension to set our frame size
        int x = (int) ((scrnsize.getWidth() - this.getWidth()) / 2); // Get width start position
        int y = (int) ((scrnsize.getHeight() - this.getHeight()) / 2); // Get height start position
        
        setBounds(x, y, a, b);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main (String[] args) {
        SizeFrame cf = new SizeFrame();   
    }
}

Try compiling and running the SizeFrame class on your system and regardless of screensize the frame should be centered in the middle of the screen and be half the size of the screen as shown in the screenshot below.

Size Frame

Panes Top

We mentioned earlier in the lesson that to use a component that inherits from the jComponent class you must place the component in a containment hierarchy whose root is a top-level Swing container such as JFrame. We can only add components directly to our JFrame content pane, or to a pane or panel that we place onto the frame. When using panes, we can add several panes on top of each other to create depth so we can use menu bars, a content area and drop-down menus for instance. You can think of our JFrame as a window frame and each pane as panes of glass we are adding to our window frame to create single, double and triple glazing. The following diagram shows how this layering works:

Set panel overlay

The whole of the content area within the frame is derived from a javax.swing.JRootPane object which extends the javax.swing.JComponent class. The JComponent method getRootPane() can be used to obtain the JRootPane object that contains a given component. The JRootPane object is made up of a glassPane, an optional menuBar and a contentPane. The layeredPane fills the entire viewable area of the JRootPane. The JLayeredPane object manages the menuBar and contentPane panes. The glassPane sits over the top of everything where it can intercept mouse movements for drag-and-drop type actions and ensure any component that needs to be on top of everything else is.

If a JMenuBar component, the optional menuBar of the JLayeredPane object, is set on the JRootPane, it is positioned along the upper edge of the frame. The contentPane is adjusted in location and size to fill the remaining area below the JMenuBar or the whole area if no JMenuBar is present.

We can access any of the panes shown in the above diagram using the reference of a JFrame object and one of the methods in the table below.

Method Description
getRootPane()Returns the internal area of the frame as a JRootPane type.
getLayeredPane()Returns the layered pane as a JLayeredPane type.
getContentPane()Returns the content pane as a Container type.
getGlassPane()Returns the glass pane as a Component type.

In the example below we create a simple frame and add a menu bar to it.


package info.java8;
import javax.swing.JFrame; // An interactive window
import javax.swing.JMenuBar; // A menu bar
import javax.swing.JMenu; // A menu
import javax.swing.JMenuItem; // A drop-down menu item

public class FrameMenuBar extends JFrame {
    private JMenuBar mb = new JMenuBar();
    private JMenuItem openItem, closeItem;
    
    // Construct the frame 
    public FrameMenuBar() {
        super("JFrame and Menu bar");
        setBounds(300, 200, 568, 218);

        setJMenuBar(mb); // Add a menu bar to our frame
        JMenu fileMenu = new JMenu("File"); // Create File menu
        openItem = fileMenu.add("Open"); // Add open option
        closeItem = fileMenu.add("Close"); // Add close option
        mb.add(fileMenu); // Add file menu to menu bar

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main (String[] args) {
        FrameMenuBar fmb = new FrameMenuBar();   
    }
}

Compiling and running the FrameMenuBar class should produce a screenshot like the one below. If you click on the File option the items we added will appear. Of course pressing these will achieve nothing as we haven't coded anything for the user clicking on the items within our file menu.

Frame Menu bar

The javax.swing.JPanel Class Top

The javax.swing.JPanel class is a generic lightweight container that we can use when we want to add one or more panels to a top-level or another background container. When we don't need to add depth to our GUI, putting our components into panels and adding these to the contentPane pane is an easy option. The JPanel class is very easy and flexible to use, allowing us to add multiple panels to a frame and panels to other panels as examples. The default layout manager for a frame is BorderLayout and to show an example of using panels we will add a panel with a different colour background to each area of this particular layout as shown in the example below.


package info.java8;
import java.awt.*; // AWT library
import javax.swing.JFrame; // An interactive window
import javax.swing.JPanel; // A lightweight container

public class FramePanels extends JFrame {
    // Construct the frame 
    public FramePanels() {
        super("Adding Panels To A JFrame");
        JPanel jp1 = new JPanel();
        jp1.setBackground(Color.blue);
        this.getContentPane().add(BorderLayout.NORTH, jp1);
        JPanel jp2 = new JPanel();
        jp2.setBackground(Color.red);
        this.getContentPane().add(BorderLayout.SOUTH, jp2);
        JPanel jp3 = new JPanel();
        jp3.setBackground(Color.black);
        this.getContentPane().add(BorderLayout.WEST, jp3);
        JPanel jp4 = new JPanel();
        jp4.setBackground(Color.green);
        this.add(BorderLayout.EAST, jp4);
        JPanel jp5 = new JPanel();
        jp5.setBackground(Color.orange);
        this.add(BorderLayout.CENTER, jp5);
        
        setBounds(300, 200, 568, 218);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main (String[] args) {
        FramePanels fp = new FramePanels();   
    }
}

Compiling and running the FramePanels class should produce a screenshot like the one below. We have added a coloured panel to each area of the default frame layout manager, BorderLayout. A point of interest here is how we can call the getContentPane() method to add to the frame or just add components directly to our frame. Prior to java this wasn't possible and you had to get a reference to the content pane to add to the frame. If you are adding components to other panes then you still need to get a reference to the pane required, as you can't add directly to any pane apart from the content pane.

Frame Panels

Lesson 3 Complete

In this lesson we looked at the javax.swing.JFrame top-level container class, adding depth to frames using panes and the javax.swing.JPanel background container class.

What's Next?

In the next lesson we look at some of the interactive lightweight Swing components.