Our Sites:  Tutorial Buzz  |  How To Tree  |  Recipe Voice  |  Golf Twist  |  DIY Click  |  Movie Lizard  |  Halloween Twist  
Search:
Submit Link
Mail to a Friend
RSS FeedReceive updates via our RSS feed

Introduction to Swing

This introduction to using Swing in Java will walk you through the basics of Swing. This covers topics of how to create a window, add controls, postion the controls, and handle events from the controls.

The Main Window
Almost all GUI applications have a main or top-level window. In Swing, such window is usually instance of JFrame or JWindow. The difference between those two classes is in simplicity – JWindow is much simpler than JFrame (most noticeable are visual differences - JWindow does not have a title bar, and does not put a button in the operating system 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. Usually, I subclass the JFrame and initialize all visual elements of that frame in the constructor.

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 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. 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.show();
   }
}

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

 

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

JButton 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"));

If you try to add more buttons to the frame, most likely only the last one added will be displayed. That is because the default behavior of JFrame content pane is to display a single component, resized to cover the entire area.

 

Grouping Components
To 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.

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

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.

For now, just note that there are also other ways of receiving event notification then installing a listener for every object on the screen. For example, the following few lines installs a global listener for the F1 key pressing:

KeyStroke ks=KeyStroke.getKeyStroke(KeyEvent.VK_F1,0);
topComponent.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks,"HELP");
topComponent.getActionMap().put("HELP",
   new AbstractAction()
   {
      public void actionPerformed(ActionEvent evt)
      {
         // do something here, display a dialog or whatever
      }
  
});

About this Tutorial
This tutorial is from The Swing Wiki which is published under the GNU Free Documentation License 1.2.

Home  |  News  |  Source Code  |  Tutorials  |  Components  |  Tools  |  Books  |  Free Magazines  |  Jobs  |  Gear  |  Hosting  |  Links
 
Copyright © 2000 - 2006 Code Beach  |    |  Privacy Policy
 
Free thumbnail preview by Thumbshots.org