| ★ wanayoo — archive 1999 http://java.oreilly.com/bite-size/java_0499.html | Nouvelle recherche | Portail wanayoo |
|
||
|
|
One of the reasons Java is exciting is that it changes so fast. The Java platform lives in "Internet time," which is a cartoonish speeded-up world that spins around Silicon Valley. Since Java was introduced in late 1995, it's grown at an astonishing rate. As a student of the Java platform, you barely have enough time to learn one release before another comes out. It's particularly hard to keep up if you're learning Java in your spare time. One area of radical change is Java's user interface (UI) toolkit. In JDK 1.0 and JDK 1.1, the Abstract Windowing Toolkit (AWT) provided the windows, buttons and other components that make up a user interface. In the world of Java 2 (JDK 1.2), however, Swing is the new UI toolkit. AWT and Swing are about as closely related as a Yugo and a Ferrari. They're both UI toolkits, but Swing's capabilities and performance far outperform AWT. Having just learned AWT, you may be dismayed to have a big mountain of information about Swing to assimilate. Don't be discouraged, however--Swing was specifically designed so that it works like AWT in many cases. For people who are already familiar with AWT, one of the most confusing things about Swing is its use of lightweight components. If you have done any reading about Swing, you have probably discovered that the AWT components you've been using now carry the stigma of being heavyweight. What does it all mean? In this column, I'll explain what heavyweight and lightweight components are and how you should use them. Everything Is a ComponentYou'll probably recall that everything you see on the screen with AWT is some subclass of java.awt.Component. Windows, dialogs, buttons, list boxes, combo boxes, and any other visual controls are all subclasses of Component. This doesn't change in Swing. All Swing components descend from javax.swing.JComponent, which itself is a descendent the original Component class. What makes a component heavyweight or lightweight? It all has to do with how components are related to the underlying operating system.Remember, no matter how much Java looks like an operating system (OS), it isn't (yet). The Java platform sits on top of an existing OS. To get to the resources of the OS, like the disk drive, network card, or display, Java uses native, platform-specific code. At some point, then, any UI toolkit built in Java has to deal with a specific OS to display its windows and components. Clumsy Old AWTAWT managed interaction with the underlying OS by using a peer system. For every UI object in your application, there was a corresponding peer object that managed a native component in the underlying OS. If you created a Button, for example, there was a ButtonPeer that worked with the underlying OS to create one of its interface buttons. If you ran your application on Windows 95, an actual Windows 95 button would be created.This has the effect that applications in AWT have controls that look appropriate for the underlying OS. If you run an AWT application on Solaris, you'll get the standard X Windows buttons, lists, and other controls. Run the same application in Windows, and you'll get standard Windows controls. However, this is one of those things where it's not clear if it's a bug or a feature. Some people think this is how a cross-platform application should work, changing chameleon-like to fit in with the host OS. Other people believe that a cross-platform application should look the same on different platforms. Regardless, the peer approach to AWT components has some serious drawbacks. First, it's very hard to port AWT from platform to platform. While it's true that most graphic OS's have basically the same visual elements, they do vary in appearance and behavior. Getting AWT to work reliably on different platforms, each with its own set of peers, was a serious problem. The other penalty of the peer approach is performance. You might think that using the OS's native components would result in fast Java applications, but exactly the opposite is true. Running all Java or all native code is pretty fast, but if you have a lot of interaction between Java and the underlying OS, it slows things down. An AWT window full of components has many peers, one for each component. Each of these represents some interaction between your application and the underlying OS. For complicated interfaces, AWT can be a real dog. Furthermore, native components are not necessarily very efficient in their memory usage. Components with peers are called heavyweight, because they tend to drag your application down into the muck. In AWT, all components are heavyweight. Swing Be Nimble, Swing Be QuickSwing uses a different technique. Instead of relying on a peer, each component is responsible for drawing itself and responding to mouse and keyboard events. These components are peerless or lightweight. At some level, of course, there must still be an interface to the underlying OS. This is done at the window level. The top level window or frame of your application, therefore, will still have a peer. If you fill the window with Swing components, no additional peers are created. The components simply draw themselves on their parent container (the window) and receive events from the parent container. This greatly reduces the interactions between your Java application and the underlying OS as compared to AWT. This means that, in general, Swing applications are much more robust across different platforms. As long as the peer interface of the top level containers is correctly implemented, the rest comes for free.As a matter of fact, Swing is written purely in Java. It relies upon the native code in AWT for the top level containers. Aside from this, however, the rest of AWT's peer system has been discarded. But because Swing is pure Java, it's a no-brainer to port it to a different platform. Another consequence of having Swing components draw themselves is that they look the same on different platforms. Furthermore, it's easy to change the appearance of the components--you just have them draw something else. Swing expands this concept into Pluggable Look & Feels, where the entire appearance of an application, including all of its components, can be changed at the drop of a hat. Like Oil and WaterThe obvious question is: can lightweight and heavyweight components coexist peacefully? Yes and no. While it's true that you can combine AWT and Swing components, the results may not always be what you're expecting.If a heavyweight component and a lightweight component overlap in any way, the heavyweight component will always appear on top. For example, a heavyweight button will always appear on top of any lightweight components, including things like menus. The rule of thumb is that you should use either heavyweight or lightweight components, but not both. If you're converting existing code, you may as well do it all at once, or at least in large container-sized chunks. Trying to get heavyweight and lightweight components to work together is probably more trouble than it's worth. Paint CarefullyOne subtlety of Swing's lightweight components is in painting. You may be used to subclassing AWT components, like Canvas, and drawing on them by overriding the paint() method. You can do this in Swing, too, but if the component you're working with contains other components, you can't just override paint(). Remember, Swing components paint themselves on their parent containers. It turns out that Swing containers are responsible for painting their children.If you override paint() in a Swing container, you should call super.paint() to take care of painting the child components. Alternately, you can override paintComponent() instead of paint(). The paintComponent() method is called by paint(); its sole responsibility is painting the component. Show Me The MoneyI'll conclude with two brief examples that illustrate heavyweight and lightweight components. The first example, HosedMenu, shows how a heavyweight component in a window can obscure a drop-down menu.
import java.awt.*;
import javax.swing.*;
public class HosedMenu Run the example; you'll see a small window with two buttons and a menu bar. The top button is lightweight; the bottom button is heavyweight. Click on the File menu. The bottom part of this lightweight menu will be obscured by the heavyweight button. (Interestingly, if you make the frame window small enough, the menu will actually be created heavyweight. Swing realizes it can't draw the whole menu on the frame window's drawing surface and creates a heavyweight component that will fit the entire menu.) The second example, TouchyFeely, shows how the appearance of Swing's lightweight components can be changed at runtime. It shows two panels with a handful of controls on each. The left half of the window is made from Swing components, while the right half contains AWT components. A menu allows you to choose from the look and feels that are available on your platform. The standard JDK includes one called Metal, one that looks like Motif, and one that looks like Windows. As you select these different look and feels, the Swing components will change their appearance to reflect the look and feel. The AWT components, on the right, won't change at all. They are heavyweight components; the underlying OS is responsible for drawing them and there is no way to change their appearance from Java.
import java.awt.*;
import javax.swing.*;
public class TouchyFeely There's not a whole lot in this example. Most of it involves creating the two panels full of controls. The tricky part is in creating the menu that controls the look and feel of the application. The call to UIManager's static getInstalledLookAndFeels() method gives us an array of objects describing the available look and feels. A menu item is created from each available look and feel. For each menu item, an associated ActionListener sets the new look and feel. ConclusionSwing is a big hunk of knowledge to assimilate. This column gives you a little rocket boost down the road to Swing proficiency by highlighting the fundamental differences between AWT and Swing components. And as always, it includes some working sample code that can serve as a springboard for your own applications.Download the Source Code.
Jonathan Knudsen is a staff writer for O'Reilly & Associates. He is the author of Java Cryptography and Java 2D Graphics.
O'Reilly Home | O'Reilly Bookstores | How to Order | O'Reilly Contacts International | About O'Reilly | Affiliated Companies © 1999, O'Reilly & Associates, Inc. |
|