Beginning Java Swing: Tutorial

Guest Posts David McMahon

Swing is Java's lightweight GUI (Graphical User Interface) for developing rich desktop applications with ease. Swing offers the customization of the look and feel for every component in an application without making big changes to the application's logical code. The aim of this article is to introduce you to Swing and create your first program. While this program will be relatively simple, it will cover the areas of Swing needed to get you up and running.



The main window of any GUI application is known as the JFrame. This is the window with the title bar, minimize, maximize and exit buttons. Within this JFrame components can be added and laid out depending on what display you want. Normally the components are first added to a JPanel and then that JPanel is in turn added to the JFrame. Think of the JFrame as being the container and the JPanel being a blank canvas to add components onto.

First Steps:
MainFrame Class:

 import java.awt.BorderLayout;
import javax.swing.JFrame;

public class MainFrame extends JFrame {

    public MainFrame() {

    super("My First Swing Application");
    setLayout(new BorderLayout());
    setSize(500, 500);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

    }
} 

Application Class:

 public class Application {

    public static void main(String[] args) {

    MainFrame frame = new MainFrame();

    }
} 

Here we have two different classes. Our Application class which holds the main method for our program, and our MainFrame class which holds the code for designing our JFrame. Inside the MainFrame class there is a constructor which creates our JFrame object when it is instantiated, so it is only natural that the code for designing the JFrame goes inside the constructor and gets created when instantiated. The call to the super() constructor accepts a String parameter and sets the title of the JFrame to whatever String you pass in.



Next step is to set the Layout that your JFrame should adopt. There are various different Layout Managers in Java and default ones which some components will adopt even if not specified, but more on that later. We set this application to use the BorderLayout which lays out its components at each compass position, North, South, East, West and Center. Next we set the size our window should be in pixels. After this the setDefaultCloseOperation() method is called which is crucial in any JFrame application, it basically determines what to do when the user clicks on the 'X' button on the top right corner of the JFrame. In this case we are telling the JFrame to simple close when this button is clicked. And finally we make our window visible by calling the setVisible() method and passing it a boolean value of true. I never really understood why the developers of Java made it to be like this, in other words is there ever a time when you don't want your JFrame window to appear? No.

We skip out into our Application class which is the starting point for our program. We simple instantiate an object from the MainFrame class and in doing so calls the constructor in which our code for designing the window is held. If you run this program you should see a window appear. If not then double check over the code illustrated above.

This process is known as 'house keeping' for any JFrame application you create, in the sense that these steps to create the JFrame window will always be the same.

Adding a JPanel to the JFrame with components:

As mentioned earlier you can place components such as , JButtons, JLabels, JTextFields etc onto the JFrame itself. But it is better programming practice to first add them to a blank canvas (JPanel) and then add the JPanel onto the JFrame. It favours code readability when your program gets complex.

Here I am going to create a ButtonPanel class that will add two JButtons onto the Panel and then the panel will be added onto the JFrame:

ButtonPanel Class:

 import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JPanel;

public class ButtonsPanel extends JPanel {

    private JButton helloButton;
    private JButton exitButton;

    public ButtonsPanel() {

    setLayout(new FlowLayout());  

    helloButton = new JButton("Hello");
    exitButton = new JButton("Exit");

    // Add the buttons to the JPanel.
    add(helloButton);
   add(exitButton);
   }
} 

Next We add that Panel onto the JFrame:
MainFrame Class:

 import java.awt.BorderLayout;
import javax.swing.JFrame;
public class MainFrame extends JFrame {

    private ButtonsPanel buttonsPanel;

    public MainFrame() {

    super("My First Swing Application"); 
    setLayout(new BorderLayout());
    setSize(500, 500); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    buttonsPanel = new ButtonsPanel(); 

    add(buttonsPanel, BorderLayout.NORTH); 

    setVisible(true); 
    }
} 

From here on out, any components we need can be added onto the JPanel object we have just created. However, there are times in which a JFrame can have multiple independant JPanels on it for the layout out of different components. For example we are going to add a JTextArea to our application next, we cannot add it onto the ButtonsPanel because the ButtonsPanel has a NORTH layout and we want our JTextArea in the center of the JFrame. Another class, we shall call it TextPanel, is needed to hold the TextArea and then we can add this Panel to the JFrame at a different location such as the Center. The two JPanels will be independent of eachother. Lets have a look:
TextPanel Class:

 import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class TextPanel extends JPanel {

    private JTextArea textArea;
    private JScrollPane scrollPane;

    public TextPanel() {

        setLayout(new BorderLayout());

        textArea = new JTextArea();

        scrollPane = new JScrollPane(textArea);

        add(scrollPane, BorderLayout.CENTER);

    }
} 

We create two instance variables, a JTextArea and a JScrollPane. The latter will be used to hold our text area within a scrollable window which is a very nice feature. In the constructor we set the Layout as before and instantiate the JTextArea object along with the JScrollPane object. Within the JScrollPane object's constructor we pass in the textArea, this is how to add a Scroll Bar to a TextArea. Finally we add the scrollpane which holds our text area onto the JPanel.

MainFrame Class:

 import java.awt.BorderLayout;
import javax.swing.JFrame;

public class MainFrame extends JFrame {

    private ButtonsPanel buttonsPanel;
    private TextPanel textPanel;

    public MainFrame() {

        super("My First Swing Application");
        setLayout(new BorderLayout());
        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        buttonsPanel = new ButtonsPanel();
        textPanel = new TextPanel();

        add(buttonsPanel, BorderLayout.NORTH);
        add(textPanel, BorderLayout.CENTER);

        setVisible(true);
    }
} 

As you can see from the code, the textpanel was added to the JFrame with a location of CENTER independent of the ButtonsPanel which has a layout of NORTH. If you type off the scope of the TextPanel you should see a scroll bar appear and the same vertically.

Finally lets add some functionality to our two buttons we created at the very start. At the moment they do nothing when clicked. Lets change that to when the Hello Button is clicked it emits a String "Hello" onto the JTextArea, and when the Exit button is clicked, yes you guessed it, it terminates the program. We do this with the use of ActionListeners, a listener is placed on the Button, when a certain action is performed such as the button is clicked, then a bit of code is executed. There are many ways to do this such as the use of an anonymous inner class, making your class implement Action Listener or to create a private class within your class and use an object of that as an ActionListener. Because our program is relatively small in that it only has two buttons, I will make our class implement ActionListener. Lets have a look:

ButtonsPanel Class:

 import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class ButtonsPanel extends JPanel implements ActionListener {

    private JButton helloButton;
    private JButton exitButton;
    private TextPanel textPanel;

    public ButtonsPanel() {

        setLayout(new FlowLayout());

        helloButton = new JButton("Hello");
        exitButton = new JButton("Exit");

        helloButton.addActionListener(this);
        exitButton.addActionListener(this);

        add(helloButton);
        add(exitButton);

    }

    public void setTextPanel(TextPanel textPanel) {
        this.textPanel = textPanel;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        JButton buttonPressed = (JButton) e.getSource();

        if (buttonPressed.equals(helloButton)) {
            textPanel.addTextToPanel("Hello\n");
        }

        else {
            System.exit(0);
        }

    }
} 

In the above code we start by making our class implement the interface ActionListener, this forces our class to override the actionPerformed() method which is where the code we want to happen when we click either button will go. We add an actionListener to our two buttons and pass in a reference of 'this' as an argument which means the object we are currently in i.e. ButtonsPanel. It then shoots down to the actionPerformed method and looks for the code we want to run. Before we code what we want to happen we first have to know which button was pressed right? We do this by using the ActionEvent object 'e' to call the getSource() method. We store this in a variable called buttonClicked, rememeber we have to typecast the e.getSource() method to type JButton to tell Java we know what we are doing as e.getSource() returns an Object. We then test to see if the button clicked was either the helloButton or the exitButton. On determining this we can then execute a logical piece of code of what we want to happen.
TextPanel Class:

 import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class TextPanel extends JPanel {

    private JTextArea textArea;
    private JScrollPane scrollPane;

    public TextPanel() {

        setLayout(new BorderLayout());

        textArea = new JTextArea();

        scrollPane = new JScrollPane(textArea);

        add(scrollPane, BorderLayout.CENTER);

    }

    public void addTextToPanel(String text) {
        textArea.append(text);
    }
} 

As you can see I added a method to the TextPanel class to be able to call it to add text to our JTextArea object. In doing this I also need to make a setTextPanel() method within the ButtonsClass to be able to work with the TextPanel and therefore enabling me to add text to the JTextArea via the addTextToPanel() method. Finally I call the buttonsPanel.setTextPanel() method in the MainFrame Class to pass in the TextArea object we created.

MainFrame:

 import java.awt.BorderLayout;
import javax.swing.JFrame;

public class MainFrame extends JFrame {

    private ButtonsPanel buttonsPanel;
    private TextPanel textPanel;

    public MainFrame() {

        super("My First Swing Application");
        setLayout(new BorderLayout());
        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        buttonsPanel = new ButtonsPanel();
        textPanel = new TextPanel();

        buttonsPanel.setTextPanel(textPanel);

        add(buttonsPanel, BorderLayout.NORTH);
        add(textPanel, BorderLayout.CENTER);

        setVisible(true);
    }
} 

When you run your code from the Application class you should get the program working perfectly. Once again this program is relatively useless in real life but it gives you an insight into the main aspects of GUI programming in Java, Creating a JFrame, Adding components onto a JPanel, adding the JPanel onto the JFrame and Setting up functionally for components to do certain tasks.