HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Okay, you've spent a year building a Java app that will take over the market, but since Swing wasn't ready and you didn't have time to wait, you used the Abstract Windowing Toolkit (AWT). Now Swing is shipping, and any app using AWT is a dinosaur. You've got to convert your work - and fast. Here's how, step by step.

To follow these procedures you need to know Java and AWT fairly well. If you used a visual tool to build your user interface and aren't familiar with concepts such as components and containers, brush up on the basics first. Keep Swing's docs handy and you can probably pick up what you need to know about it as you go.

First, in each of your source files using AWT add:

import com.sun.java.swing.*;

If you're using panel borders, also add:
import com.sun.java.swing.borders.*;

If you're using the Standard Extension version of Swing, remember to substitute "javax" wherever you'd use "com.sun.java" - except, however, for the import statements, where you change "java.awt." to "com.sun.java.swing.J". Be sure to include the trailing "." in "java.awt.". If you're not concerned about name space collisions, you can just change "java.awt." to "J". Then you can change any other occurrences of "Frame" to "JFrame", "Dialog" to "JDialog", "List" to "JList", etc. In general, you simply need to add a "J" to the type. The AWT component's member functions are almost the same for Swing. For reliability, don't mix AWT and Swing components; instead, convert them all to Swing.

After you've added "com.sun.java.swing.J" to "Checkbox", change "JCheckbox" to "JCheckBox", with a capital "B". Next, replace any JChoice with JComboBox, and any Checkboxes (which are actually radio buttons) with JRadioButton. Then replace each corresponding CheckboxGroup with a ButtonGroup.

You also must replace any JChoice with JComboBox, change "getState()" to "isSelected()" and "setState(state)" to "setSelected(state)".

For in-source files built with Visual Café you must delete any lines that begin with //{{ or //}}. Then, in the constructor, remove:

setLayout( . . . );
addNotify();
resize( . . . );
setBackground(new Color( . . . ));

And for each component remove:

component.reshape( . . . );
component.setForeground( . . . );

and if present

component.setLayout(null);

Don't delete any other setLayout() calls.

Then change "new BorderLayout(0,0)" to "new BorderLayout()". If the show() member function was automatically generated, remove it, but if you created your own code to show(), leave it and be sure to override setVisible() to call your code. Next, change "JList(0,false)" to "JList()" and change "FlowLayout(FlowLayout.CENTER,5,5)" to "FlowLayout()".

In the parameter for event-handling functions, such as a button click or menu item, change "Event" to "java.awt.event.ActionEvent" and replace any symantec.itools.awt components with the appropriate Swing component.

For example, if you're using TabPanel, replace it with JTabbedPane. Symantec's components don't map closely to Swing components.

Also, change the order of component initialization so all components are added depth first. This means all components in a container must be added before that container is added to an enclosing container. Just look for calls to "add" and arrange them so the innermost appear first and the outermost last. Then replace any AWT listeners and handleEvent methods with Swing listeners.

Add a call to addListeners() in the constructor. Listing 1 contains some example code.

For containers with a BorderLayout, change:

container.add("Center", component);
to:
container.add(component, BorderLayout. CENTER);

Change East, West, North and South the same way.

For readability you may want to delete "com.sun.java.swing." except in the import statements. Pay close attention to the Swing threading rules. Swing components don't automatically add scroll bars as needed. If you want a component to scroll, first add the component to a JScrollPane, then add the scrollpanel to the container. Here's an example:

JScrollPane scrollPane = new JScrollPane ();
scrollPane. getViewport(). add ( myComponent );
myContainer. add ( scrollPane );

In some Swing containers, including JApplet, JDialog, JFrame, JInternalFrame and JWindow, you can't use add(), setLayout(), etc., directly. Instead, use getContentFrame() to get the right container. This is one of the few serious design errors in Swing. Set a layout explicitly for the container. The code used to handle it looks like this:

Container c = myContainer. getContentPane ();

c. setLayout ( new BorderLayout () );
c. add ( myComponent, BorderLayout. CENTER );

Don't forget that BorderLayout now has constants, such as CENTER and SOUTH, which are used for positioning in place of the old string literals. These constants are now the second parameter to add(), not the first.

In AWT applications there were advantages to laying out your components in the addNotify() member function. Lay out Swing applications in the constructor, as you always have for applets. Remember to lay out inner containers first.

Although you should be able to set up a ListModel or just use DefaultListModel with JList, in practice it seems to be more reliable to maintain a separate data Vector for each JList. Pass that Vector to the JList constructor. When you want to add, insert or delete data in the JList, make the changes to your Vector. Then reset the JList's data model to the changed Vector using setListData(). It's important to make changes only to the Vector that you passed to JList's constructor. Be careful that you don't accidentally pass a different Vector to setListData(), or it won't work.

To add an item to a list, you'll use code such as:

JList list;
Vector listVector;

public MyClass () {
listVector = new Vector ();
list = new JList (
}

void addItemToList ( String s ) {
listVector. addElement ( s );
list. setListData ( listVector );
}

After you add all your components to their containers, call pack() on the outermost container. Do this before you do anything that needs the size of the container, such as centering it on the screen. Make sure Swing is in the classpath and run your application. You should see how it looks in Swing, and it should look about the same on every platform. Now your Java code is finally "write once, run anywhere"!

About the Author
Doug Porter is cofounder and director of research and development for DeNova, Inc., manufacturer of the Java installer J'Express. He has more than 19 years' experience as a professional software engineer with three years experience in Java. He's just finishing his third commercial Java application. Doug can be reached at [email protected]

 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.