Converting to Swing |
The primary focus when converting a 1.1 AWT-based program to Swing is to modify the program to use Swing components instead of AWT components. This page outlines the steps for doing this. Each step applies to all programs--applications and applets--unless specifically noted otherwise.Step 1: Save a copy of the AWT-based program.
You will need to copy all of the programs files, including the.java
files and the.class
files. You will need this copy for several reasons:
- Any users who can't run Swing programs will need to run the old AWT-based program.
- You'll need to refer to the source during the conversion process.
- After conversion, you should run both versions of your program side by side to compare them.
- After conversion, you can compare the source code of both versions to apply what you learned to other programs you need to convert.
Step 2: Remove any
java.awt
import statements.This step puts the compiler to work for you. It's handy to remove all of the AWT imports even if your program still uses some of the AWT classes--like its layout managers--because, without the AWT imports, the compiler generates a "not found" error for each AWT component used by your program and the line number where it's used. This helps to locate each AWT component used by your program so that you can replace it with its Swing equivalent. In Step 9, you will add back in the imports for the AWT classes that you really need.Step 3: If your program is an applet, remove any
java.applet
import statements.You don't need the oldApplet
class or the oldjava.applet
package because your Swing applet will be a subclass of Swing'sJApplet
class. So remove whichever of these import statements is in your program:importjava.applet.Applet
; or importjava.applet.*
;Step 4: Import the main Swing package.
Add the following import statement to your program.This imports all of the Swing components plus some of Swing's other classes. If you want, you can be more meticulous and add one import statement per Swing class you use.importjavax.swing.*
;Step 5: Be aware of thread-safety issues!
Before you go further, remind yourself of this important fact: Although AWT is thread-safe, Swing is not. You must take this into consideration when converting your programs.Most programs modify components in event handling methods and painting methods, which are called from the event-dispatching thread. Modifying a component in those methods is safe because the event-dispatching thread is guaranteed to be thread-safe. [PENDING: check wording of previous sentence] If your program modifies a component anywhere else, you must take explicit action to make it thread-safe.
This tutorial contains two sections about Swing and threads. First, Threads and Swing provides conceptual coverage. Next, How to Use Threads contains practical information and examples.
Step 6: Change each AWT component to its closest Swing equivalent.
The table provided in our resources section, Swing Replacements for AWT Components, lists each AWT component and its closest Swing equivalent. Use it as a guide for choosing a replacement for each AWT component used in your program.In the best case, the AWT component and its Swing replacement are source-compatible and a simple name change is all that's required. For example, to convert from an AWT button to a Swing button, you just change all occurrences of
Button
toJButton
in your program. Here's a short example of an AWT code snippet and its Swing equivalent to illustrate. The underlined code shows the differences between the two programs.
AWT Code Swing Code Button button = new Button("A Button"); button.addActionListener(this); JButton button = new JButton("A Button"); button.addActionListener(this);You'll be happy to learn that a large number of Swing components are source-compatible with their AWT counterparts. You can refer to the javadoc for each Swing component class to find out if it is source-compatible with its AWT counterpart and to what degree.
Conversely, some Swing components are not source-compatible with the AWT component they replace. So, for some AWT components, you have to re-write some code when replacing it with a Swing component. Furthermore, you might choose to make unrequired changes to take advantage of Swing features. For example, you might want to add an image to your button, or you might want to support accessibility by calling the
setLabelFor
method on labels associated with other components. Conversion Resources has information to help you with conversions that require more than a simple name change and optional conversions.Step 7: Investigate Swing's other components.
You might be able to improve your UI by using features available only in Swing components (such as images on buttons) or by using Swing's more sophisticated components not available in the AWT. You might also be able to replace a component you wrote yourself with a standard Swing component or a customized Swing component. Components completely new to Swing include tables, trees, color choosers, and so on.Step 8: Change calls to the
add
andsetLayout
methods.AWT programs add components directly to and set the layout manager directly on a top-level container (a frame, dialog, or applet). In contrast, Swing programs add components to and set the layout manager on the top-level container's content pane. The first row of the following table shows some typical AWT code for adding components to a frame and setting its layout manager. The second and third rows show two different Swing conversions.
AWT code frame.setLayout(new FlowLayout()); frame.add(button); frame.add(label); frame.add(textField);Obvious Swing Conversion
(don't do this) frame.getContentpane().setLayout(new FlowLayout()); frame.getContentPane().add(button); frame.getContentPane().add(label); frame.getContentPane().add(textField);Efficient Swing Conversion
(do this instead) Container contentPane = frame.getContentPane(); contentPane.setLayout(new FlowLayout()); contentPane.add(button); contentPane.add(label); contentPane.add(textField);You'll note that the Swing code in the second row calls
getContentPane
multiple times, which is inefficient if your program uses a lot of components. The Swing code in the third row improves the code, by getting the content pane once, caching it in a variable, and using the variable to add components to it and set the layout manager.Step 9: Use the compiler to flesh out any more needed changes.
After you've modified the source code as indicated in the prevous steps, use the compiler to try to compile your program.During this step, you are basically getting the compiler to help you identify any conversions you might have overlooked. Don't expect your program to compile the first time and do expect several iterations!javac MyClass.javaThe compiler can help you:
Fix all problems reported by the compiler until the program compiles.
- Find each AWT component that you forgot to convert to its Swing equivalent. If you removed all of the
java.awt
import statements from your program as suggested in step 2, the compiler will display an error message like this for each AWT component remaining in your program.TextEventDemo.java:23: Class Button not found in type declaration. Button button = new Button("Clear"); ^- Identify which AWT classes your program still needs. If you removed all of the
java.awt
import statements from your program as suggested in step 2, the compiler will display an error message like this for AWT classes you still need.The AWT classes you might still need in a Swing program are layout managers,TextEventDemo.java:17: Class BorderLayout not found in type declaration. BorderLayout layout = new BorderLayout(); ^Color
,Dimension
,Point
,Insets
, and so on. Add one import statement per AWT class. Or, if you're sure that you've replaced all the AWT components with Swing components, import the entirejava.awt
AWT package again.
- Locate any source-incompatibilities between the AWT component and its Swing replacement. These typically show up as compiler errors about undefined methods. For example, although AWT text components have an
addTextListener
method, Swing text components don't. The compiler generates an error message like the following one indicating thatJTextField
doesn't have such a method.TextEventDemo.java:22: Method addTextListener(TextEventDemo. MyTextListener) not found in class javax.swing.JTextField. textField.addTextListener(new MyTextListener("Text Field")); ^- Remove uses of deprecated API. Use the compiler's
-deprecation
flag to get details about any deprecated classes or methods used by your program and the line numbers where they are used.Refer to the javadoc for the deprecated class or method for information about what classes or methods to use instead.javac -deprecation MyClass.javaStep 10: Run the Swing program.
Use the interpreter or the Applet Viewer to run your program:java MyClass or appletviewer MyApplet.htmlIf you forgot to modify any calls to
add
orsetLayout
, you will discover that during this step. If you did, the runtime system displays a message like this one (the error message forsetLayout
is similar):Go back to the source, search forjava.lang.Error: Do not use MultiListener.add() use MultiListener.getContentPane().add() instead at javax.swing.JApplet.createRootPaneException(Compiled Code) at javax.swing.JApplet.addImpl(Compiled Code) at java.awt.Container.add(Compiled Code) at MultiListener.init(Compiled Code) at sun.applet.AppletPanel.run(Compiled Code) at java.lang.Thread.run(Compiled Code)add
orsetLayout
, fix the problem, then compile and run again.If you program is an applet, consider how your users will run it. Refer to Converting Applets.
Step 11: Compare the Swing Version to the AWT version.
Although you probably want the programs to be similar, be open to improvements offered by Swing and any differences inherent in the two GUIs.[PENDING: add something about choosing the L&F? Anything else?]
Step 12: Clean up!
Now is the time to clean up your code. If you hacked any code together to get around some of AWT's deficiencies or bugs, clean it up now!
Converting to Swing |