Click here to send us your inquires or call (852) 36130518
Is this your first time here? SwingWiki is a Java Swing Developer community site with an big archive of Swing-related usenet groups and mailing lists, but also tips, tricks and articles and book reviews written by your colleagues from around the world. If you came here through a search engine and did not find what you were looking for, make sure to check the wiki table of contents.

Introduction to Swing

The main window

Almost all GUI applications have a main or top-level window. In Swing, such a window is usually an instance of JFrame or JWindow. The difference between those two classes is in simplicity – JWindow is much simpler than JFrame (the most noticeable differences are visual - JWindow does not have a title bar, and does not put a button in the task bar). So, your applications will almost always start with a JFrame.

Though you can instantiate a JFrame and add components to it, a good practice is to encapsulate and group the code for a single visual frame in a separate class. Many Java programmers subclass JFrame and initialize all visual elements of that frame in the constructor. Another approach is also in growing use, using a factory to instantiate a JFrame and initialize everything there.

Always pass a title to the parent class constructor – that String will be displayed in the title bar and on the task bar. Also, remember to always initialize the frame size (by calling setSize(width,height)), or your frame will not be noticeable on the screen.

package com.neuri.handsonswing.ch1;
 
import javax.swing.JFrame;
 
public class MainFrame extends JFrame{
public MainFrame(){
super("My title");
setSize(300,300);
}
}

Now you have created your first frame, and it is time to display it. The main frame is usually displayed from the main method – but resist the urge to put the main method in the frame class. Always try to separate the code that deals with visual presentation from the code that deals with application logic – starting and initializing the application is part of application logic, not a part of visual presentation. A good practice is to create an Application class, that will contain initialization code.

package com.neuri.handsonswing.ch1;
public class Application {
public static void main(String[] args) {
// perform any initialization
MainFrame mf=new MainFrame();
mf.setVisible(true);
}
}

 Empty frame with a title bar and task bar button

If you run the code now, you will see an empty frame. When you close it, something not quite obvious will happen (or better said, will not happen). The application will not end. Remember that the Frame is just a visual part of the application, not application logic – if you do not request application termination when the window closes, your program will still run in the background (look for it in the process list). To avoid this problem, add the following line to the MainFrame constructor:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Before Java2 1.3, you had to register a window listener and then act on the window closing event by stopping the application. Since Java2 1.3, you can specify a simple action that will happen when a window is closed with this shortcut. Other options are HIDE_ON_CLOSE (the default – window is closed but application still runs) and DO_NOTHING_ON_CLOSE (rather strange option that ignores a click on the X button in the upper right corner).

If you might have more than one main window, or you might have sparked off some threads to do some other processing, that should continue after the user closes the window, use WindowConstants.DISPOSE_ON_CLOSE instead of JFrame.EXIT_ON_CLOSE.

Adding components

Now is the time to add some components to the window. In Swing (and the Swing predecessor, AWT) all visual objects are subclasses of Component class. The Composite pattern was applied here to group visual objects into Containers, special components that can contain other components. Containers can specify the order, size and position of embedded components (and this can all be automatically calculated, which is one of the best features of Swing).

Button in a frame content paneJButton is a component class that represents a general purpose button – it can have a text caption or an icon, and can be pressed to invoke an action. Let’s add the button to the frame (note: add imports for javax.swing.* and java.awt.* to the MainFrame source code so that you can use all the components).

When you work with JFrame, you want to put objects into it’s content pane – special container intended to hold the window contents. Obtain the reference to that container with the getContentPane() method.

 
Container content=getContentPane();
content.add(new JButton("Button 1"));
 

The default layout manager of the content pane is BorderLayout. By default when you add a component to a BorderLayout without specifying a contraint the component is added to the CENTER of a BorderLayout. This will cause the component to take up all remaining space available in the container (the content pane in this case). To add other components to the content pane specify a different BorderLayout constraint.

Container content=getContentPane();
content.add(new JButton("Button 2"), BorderLayout.NORTH);

Grouping components

Buttons grouped in a panelTo put more than one component into a place intended for a single component, group them into a container. JPanel is a general purpose container, that is perfect for grouping a set of components into a “larger” component. So, let’s put the buttons into a JPanel:

JPanel panel=new JPanel();
panel.add(new JButton("Button 1"));
panel.add(new JButton("Button 2"));
panel.add(new JButton("Button 3"));
content.add(panel);

Layout management basics

One of the best features of Swing is automatic component positioning and resizing. That is implemented trough a mechanism known as Layout management. Special objects – layout managers – are responsible for sizing, aligning and positioning components. Each container can have a layout manager, and the type of layout manager determines the layout of components in that container. There are several types of layout managers, but the two you will most frequently use are FlowLayout (orders components one after another, without resizing) and BorderLayout (has a central part and four edge areas – component in the central part is resized to take as much space as possible, and components in edge areas are not resized). In the previous examples, you have used both of them. FlowLayout is the default for a JPanel (that is why all three buttons are displayed without resizing), and BorderLayout is default for JFrame content panes (that is why a single component is shown covering the entire area).

Layout for a container is defined using the setLayout method (or usually in the constructor). So, you could change the layout of content pane to FlowLayout and add several components, to see them all on the screen.

The best choice for the window content pane is usually a BorderLayout with a central content part and a bottom status (or button) part. The top part can contain a toolbar, optionally.

Layout combinations Now, let’s combine several components and layouts, and introduce a new component – JTextArea. JTextArea is basically a multiline editor. Initialize the frame content pane explicitly to BorderLayout, put a new JTextArea into the central part and move the button panel below.

package com.neuri.handsonswing.ch1;
 
import java.awt.*;
import javax.swing.*;
 
public class MainFrame extends JFrame{
public MainFrame(){
super("My title");
setSize(300,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content=getContentPane();
content.setLayout(new BorderLayout());
JPanel panel=new JPanel(new FlowLayout());
panel.add(new JButton("Button 1"));
panel.add(new JButton("Button 2"));
panel.add(new JButton("Button 3"));
content.add(panel, BorderLayout.SOUTH);
content.add(new JTextArea(), BorderLayout.CENTER);
}
}

Notice that the layouts for content pane and the button panel are explicitly defined. Also notice the last two lines of code – this is the other version of add method, which allows you to specify the way the component is added. In this case, we specify the area of BorderLayout layout manager. Central part is called BorderLayout.CENTER, and other areas are called BorderLayout.NORTH (top), BorderLayout.SOUTH (bottom), BorderLayout.WEST (left) and BorderLayout.EAST (right). If you get confused about this, just remember land-maps from your geography classes.

Scrolling

Scrolling Now, type a few lines of text into the text area – once you type enough lines (or press Enter enough times), the cursor will disappear from the screen. Swing is different from other GUI toolkits, and visual components do not support scrolling unless you tell them to – but, on the other hand, this way you can put scrollbar around almost anything. To enable scrolling, just put the component (or a container with other components) into a JScrollPane – this is a special container that adds scrollbars to it’s content. Change the last line of the previous class to

content.add(new JScrollPane(new JTextArea()), BorderLayout.CENTER);

to see a scrolling text area inside your window.

Other interesting components

Experiment a bit with other components that you will be using often. Try to add the following components in the example frame:

  • JTextField - a single line text field. For example, the following line will add a text field with 10 spaces for characters to the panel:
  • JLabel - a simple textual label. Use this component in front of text fields to describe their function.
  • JComboBox - a drop down menu (optionally editable)

other components in action

panel=new JPanel(new FlowLayout());
panel.add(new JLabel("Enter your name"));
panel.add(new JTextField(10));
String options[]=new String[]{
"Option 1","Option 2","Option 2"
};
panel.add(new JComboBox(options));
content.add(panel, BorderLayout.NORTH);

Handling actions and events

Now that you have learned how to put components on the screen, you will learn how to react to user actions with those components. The central mechanism for this is the Observer pattern, implemented in Swing with event listeners. Components publish notifications about events, and event listeners receive these notifications. For example, to execute a code when user presses a button, you should define a listener for the button pressing event and register it with that button.

Button pressed

package com.neuri.handsonswing.ch1;
 
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.*;
 
public class MainFrame extends JFrame{
public MainFrame(){
super("My title");
setSize(300,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content=getContentPane();
content.setLayout(new BorderLayout());
JPanel panel=new JPanel(new FlowLayout());
JButton button1=new JButton("Button 1");
panel.add(button1);
button1.addActionListener( new MyButtonListener(this));
panel.add(new JButton("Button 2"));
panel.add(new JButton("Button 3"));
content.add(panel, BorderLayout.SOUTH);
content.add(new JScrollPane(new
JTextArea()), BorderLayout.CENTER);
panel=new JPanel(new FlowLayout());
panel.add(new JLabel("Enter your name"));
panel.add(new JTextField(10));
String options[]=new String[]{
"Option 1","Option 2","Option 2"
};
panel.add(new JComboBox(options));
content.add(panel, BorderLayout.NORTH);
}
private class MyButtonListener implements ActionListener{
private JFrame parentComponent;
MyButtonListener(JFrame parentComponent){
this.parentComponent=parentComponent;
}
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(
parentComponent,"BUTTON PRESSED!");
}
}
}

In this example, we created an ActionListener and attached it to a button. ActionListener interface has just one method: actionPerformed. That method is called when an action occures. The event type ActionEvent is the most common in Swing - most components produce an ActionEvent. Components may also produce other events - such as change of the current selection, text or size. For now, you should be most concerned with ActionEvent. In any case, in an IDE that can display methods of a class and look for methods that begin with add and end with Listener (for example, addFocusListener) to see what listener/event types a component supports.

One more interesting thing in this example is usage of class JOptionPane. That class has many utility methods that help you display standardised input dialogs and message dialogs.

This being said, it is time to note that the above example is not written in the style usual for Swing. Since the only usage of a listener is to call a method, it is ofter written as an anonymous inner class.

button1.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(MainFrame.this,"BUTTON PRESSED!");
}
});

This way, you do not have to write another class like MyActionListener for every listener - the code is much shorter and (arguably) easier to read. Note the strange notation for the parent component - (MainFrame.this). Since the anonymous action listener instance is a fully-fledged object, using only this would point to that object. MainFrame.this points to the instance of MainFrame that contains the embedded action listener.

Event processing is described in more detail in chapter 3, Interacting with Users.


Next: Building Screen Elements | Hands On Swing Table of Contents | Other Swing Books

 

Comments? Corrections? Contact us or Login to edit pages directly (registration is free and takes less than displaying a JLabel)
  handson/introduction_to_swing.txt · Last modified: 2006/09/14 19:47 by 86.133.133.175 (gojko)
 
Recent changes | RSS changes | Table of contents | News Archive | Terms And Conditions | Register | The Quest For Software++| Ruby Resources
FitNesse Resources