Creating Swing apps

Our first Swing app will be simple, and it will only mimic the applet and AWT apps we've seen by displaying the same message as they did. To put together this app, create a project named Ch06_03 and add the class Ch06_03 with a main method to the org.eclipsebook.ch06 package. We'll need these imports in this example:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


In this example, we'll derive a new class, Panel, from the Swing JPanel class to display the message in:

class Panel extends JPanel {
 .
 .
 .
}


The JPanel class has a method named paintComponent and we'll override that method to display the text message like this:

class Panel extends JPanel {
 Panel( )
 {
 setBackground(Color.white);
 }
 public void paintComponent (Graphics g)
 {
 super.paintComponent(g);
 g.drawString("Hello from Eclipse!", 60, 100);
 }
}


The main class in this app, Ch06_03, will extend the Swing JFrame class:

public class Ch06_03 extends JFrame {
 .
 .
 .


In the Ch06_03 class constructor, we'll create an object of the Panel class and add it to the content pane of the current JFrame object:

Panel p;
public Ch06_03( ) {
 super("Swing app");
 Container contentPane = getContentPane( );
 p = new Panel( );
 contentPane.add(p);
}


All that's left is to create a new object of the Ch06_03 class in the main method, display that object with the setVisible method, and handle the window closing with the WindowAdapter class as we did in AWT. You can see how this works in the main method in Example 6-3.

Example 6-3. A simple Swing app
package org.eclipsebook.ch06;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Ch06_03 extends JFrame {
 Panel p;
 public Ch06_03( ) {
 super("Swing app");
 Container contentPane = getContentPane( );
 p = new Panel( );
 contentPane.add(p);
 }
 public static void main(String args[]) {
 final JFrame f = new Ch06_03( );
 f.setBounds(100, 100, 300, 300);
 f.setVisible(true);
 f.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 f.addWindowListener(new WindowAdapter( ) {
 public void windowClosing(WindowEvent e) {
 System.exit(0);
 }
 });
 }
}
class Panel extends JPanel {
 Panel( )
 {
 setBackground(Color.white);
 }
 public void paintComponent (Graphics g)
 {
 super.paintComponent(g);
 g.drawString("Hello from Eclipse!", 60, 100);
 }
}


You can see the results when you run this app in a Swing window in Screenshot-4.

Screenshot-4. A Swing app
Java figs/ecps_0604.gif

One of the original motivations behind Swing was to let developers tailor the "look-and-feel" of their apps to various operating systems. That's become a big issue in Eclipse, which comes with IBM's Standard Widget Toolkit (SWT), a replacement toolkit for AWT and Swing, built-in. SWT is the focus of the next two chapters, but before we get there, we'll take a look at what Swing has to offer for pluggable look-and-feels in a new example, Ch06_04. To set a Swing program's look-and-feel, you use the UIManager class's setLookAndFeel method. In this example, we'll add three radio buttons to support the Metal (Sun's Java look-and-feel), Motif, and Windows look-and-feels. First, we'll derive the Ch06_04 class from the Swing JFrame class and create the radio buttons:

public class Ch06_04 extends JFrame {
 JRadioButton b1 = new JRadioButton("Metal"),
 b2 = new JRadioButton("Motif"),
 b3 = new JRadioButton("Windows");


As in the previous example, we'll use a JPanel object for display purposes. Here, we'll display an assortment of controls, buttons, text fields, labels, checkboxes, and so on, and we'll add an ActionListener to the Metal/Motif/Windows radio buttons:

class Panel extends JPanel implements ActionListener
{
 public Panel( ) {
 add(new JButton("JButton"));
 add(new JTextField("JTextField"));
 add(new JCheckBox("JCheckBox"));
 add(new JRadioButton("JRadioButton"));
 add(new JLabel("JLabel"));
 add(new JList(new String[] {
 "JList Item 1", "JList Item 2", "JList Item 3"}));
 add(new JScrollBar(SwingConstants.HORIZONTAL));
 ButtonGroup group = new ButtonGroup( );
 group.add(b1);
 group.add(b2);
 group.add(b3);
 b1.addActionListener(this);
 b2.addActionListener(this);
 b3.addActionListener(this);
 add(b1);
 add(b2);
 add(b3);
 .
 .
 .


All that's left is to call the UIManager class's setLookAndFeel method inside the actionPerformed method to switch the look-and-feel as needed. You can see how that works in the full code, which appears in Example 6-4.

Example 6-4. The Ch06_04.java Swing app with pluggable look-and-feel
package org.eclipsebook.ch06;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Ch06_04 extends JFrame {
 JRadioButton b1 = new JRadioButton("Metal"),
 b2 = new JRadioButton("Motif"),
 b3 = new JRadioButton("Windows");
 public Ch06_04( ) {
 super("Swing app");
 Container contentPane = getContentPane( );
 contentPane.add(new Panel( ), BorderLayout.CENTER);
 }
 public static void main(String args[]) {
 final JFrame f = new Ch06_04( );
 f.setBounds(100, 100, 300, 300);
 f.setVisible(true);
 f.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 f.addWindowListener(new WindowAdapter( ) {
 public void windowClosing(WindowEvent e) {
 System.exit(0);
 }
 });
 }
 class Panel extends JPanel implements ActionListener
 {
 public Panel( ) {
 add(new JButton("JButton"));
 add(new JTextField("JTextField"));
 add(new JCheckBox("JCheckBox"));
 add(new JRadioButton("JRadioButton"));
 add(new JLabel("JLabel"));
 add(new JList(new String[] {
 "JList Item 1", "JList Item 2", "JList Item 3"}));
 add(new JScrollBar(SwingConstants.HORIZONTAL));
 ButtonGroup group = new ButtonGroup( );
 group.add(b1);
 group.add(b2);
 group.add(b3);
 b1.addActionListener(this);
 b2.addActionListener(this);
 b3.addActionListener(this);
 add(b1);
 add(b2);
 add(b3);
 }
 public void actionPerformed(ActionEvent e) {
 JRadioButton src = (JRadioButton)e.getSource( );
 try {
 if((JRadioButton)e.getSource( ) == b1)
 UIManager.setLookAndFeel(
 "javax.swing.plaf.metal.MetalLookAndFeel");
 else if((JRadioButton)e.getSource( ) == b2)
 UIManager.setLookAndFeel(
 "com.sun.java.swing.plaf.motif.MotifLookAndFeel");
 else if((JRadioButton)e.getSource( ) == b3)
 UIManager.setLookAndFeel(
 "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
 }
 catch(Exception ex) {}
 SwingUtilities.updateComponentTreeUI(getContentPane( ));
 }
 }
}


When you run this app, you'll see a number of controls in the launched window, as seen in Screenshot-5. This figure shows the default "Metal" look that Sun developed as a cross-platform look.

Screenshot-5. The Metal look
Java figs/ecps_0605.gif

On the other hand, selecting the Motif radio button changes the look-and-feel to Motif, as you see in Screenshot-6.

Screenshot-6. The Motif look
Java figs/ecps_0606.gif

And selecting the Windows radio button displays the Windows look-and-feel, as you see in Screenshot-7.

Screenshot-7. The Windows look
Java figs/ecps_0607.gif

As you can see, Swing makes an effort to stay up-to-date with various looks. Unfortunately, the various operating systems that Swing emulates have changed faster than Swing has, and Swing is substantially behind the times now, especially when it comes to Windows.

Screenshot

We'll talk more on this issue in the next chapter when we start dealing with SWT.


Now that we're designing GUIs, you may be asking yourself, wouldn't it be great if Eclipse came with visual tools that would let you simply drag and drop controls into place? Many developers have asked for that, but it doesn't appear likely that Eclipse will include a drag-and-drop GUI toolbox soon. However, there are a number of Eclipse plug-ins that provide this functionality—some are commercial, some are free. Next, we'll take a look at a free plug-in that lets you build Swing apps.

      
Comments