Java Tip 90: Accelerate your GUIs -
JavaWorld
Tutorial Details:
Java Tip 90: Accelerate your GUIs
Java Tip 90: Accelerate your GUIs
By: By Mark Roulo
Improve GUI performance using 'lazy' evaluation
low graphical user interfaces (GUIs) are a common complaint directed at Java. While constructing snappy GUIs can take time and effort, I'll present a class that can speed up GUIs with little extra work on your part. For serious GUI improvements, this is only the first step; however, it's an excellent one because it's simple. Sometimes this class improves performance enough without any additional work.
The approach
The approach is easily stated: delay building GUI components until necessary. On a macro scale, all Java programs already do this by default. Who, after all, builds all the possible frames and windows of a program while initializing? However, the class I present here allows you more fine-grained, lazy construction than that already offered by Java.
Three observations led to the utility class I built to support lazy construction of GUI components. First, most GUI panels are simple and initialize fast enough without any extra work.
Panels that cram a huge number of GUI components onto the screen are responsible for most slow initializations. These panels tend to be of two types, either tabbed panes or scroll panels.
Second, until a GUI component needs to be viewed, it usually doesn't need to be constructed. Third, GUI components cannot be seen until one of the following methods is called:
public void paint (Graphics)
public void paintComponents(Graphics)
public void paintAll (Graphics)
public void repaint ()
public void repaint (long)
public void repaint (int, int, int, int)
public void repaint (long, int, int, int, int)
public void update (Graphics)
The idea is to create a utility panel class that moves most of the GUI construction code out of the initializers and constructors. Instead, this code is placed in a function called lazyConstructor() . This function does most of the work ordinarily done by the GUI constructor, but is not itself a constructor. This utility panel class ensures that the lazyConstructor method is called once before any paint or update methods are called.
Using this panel class inside tab panels lets the tabbed panes construct faster because only one visible tab panel needs to be constructed initially.
The code
The code for this class looks like this:
import java.awt.*;
/**
* LazyPanel is an abstract base class that provides functionality
* to defer populating a Panel object until it is actually viewed.
* This is extremely useful when using CardLayout and tab panel
* views because it allows the construction of the subviews to
* be done on a pay-as-you-go basis instead of absorbing all the cost
* of construction up front.
*
* If subclasses choose to override any of the following methods,
* it is their responsibility to ensure their overridden methods
* call the parent's method first . The methods are:
*
* public void paint (Graphics)
* public void paintComponents(Graphics)
* public void paintAll (Graphics)
* public void repaint ()
* public void repaint (long)
* public void repaint (int, int, int, int)
* public void repaint (long, int, int, int, int)
* public void update (Graphics)
*
* Each of these methods ensures the panel is constructed
* and then simply forwards the call to the parent class.
*
* You use this class by extending it and moving as much of the
* constructor code as possible from the child class into the method
* lazyConstructor. An example of using LazyPanel is:
*
*
*
* import java.awt.*;
*
* class BusyPanel extends LazyPanel
* {
* public BusyPanel (int rows, int cols)
* {
* this.rows = rows;
* this.cols = cols;
* }
*
* protected void lazyConstructor()
* {
* setLayout (new GridLayout (rows, cols));
* for (int i = 0; i < rows * cols; ++i)
* {
* add (new Button (Integer.toString (i + startValue)));
* ++startValue;
* }
* }
*
* static private int startValue = 0;
*
* private int rows;
* private int cols;
* }
*
* You use it like this:
*
* import java.awt.*;
* import java.awt.event.*;
*
* class TestFrame extends Frame
* {
* public TestFrame ()
* {
* setLayout (new BorderLayout ());
* add (nextButton, "South");
*
* framePanel.setLayout (layout);
* for (int i = 0; i < 30; ++i)
* framePanel.add (new BusyPanel (8, 8), "");
* add (framePanel, "Center");
*
* nextButton.addActionListener (
* new ActionListener()
* {
* public void actionPerformed (ActionEvent event)
* {
* layout.next (framePanel);
* }
* }
* );
*
* setSize (400, 300);
* }
*
* private CardLayout layout = new CardLayout();
* private Button nextButton = new Button ("Next Panel");
* private Panel framePanel = new Panel();
*
* static public void main (String args[])
* {
* (new TestFrame()).show();
* }
* }
*
* To see the advantage of using the LazyPanel, try moving the code
* in the lazyConstructor() method into the constructor of BusyPanel,
* recompile and rerun the example. The extra lag in startup time
* is what the LazyPanel class is intended to remove.
*
* This works with swing, too. Just modify the LazyPanel to
* extend JPanel instead of Panel.
*/
public abstract class LazyPanel extends Panel
{
// We want to call the lazyConstructor only once.
private boolean lazyConstructorCalled = false;
// Some versions of Swing called paint() before
// the components were added to their containers.
// We don't want to call lazyConstructor until
// the components are actually visible.
private boolean isConstructorFinished = false;
/**
* Make a LazyPanel.
*/
protected LazyPanel ()
{
isConstructorFinished = true;
}
public void paint (Graphics g)
{
callLazyConstructor();
super.paint (g);
}
public void paintAll(Graphics g)
{
callLazyConstructor();
super.paintAll (g);
}
public void paintComponents (Graphics g)
{
callLazyConstructor();
super.paintComponents (g);
}
public void repaint ()
{
callLazyConstructor();
super.repaint();
}
public void repaint (long l)
{
callLazyConstructor();
super.repaint (l);
}
public void repaint (int i1, int i2, int i3, int i4)
{
callLazyConstructor();
super.repaint (i1, i2, i3, i4);
}
public void repaint (long l, int i1, int i2, int i3, int i4)
{
callLazyConstructor();
super.repaint (l, i1, i2, i3, i4);
}
public void update (Graphics g)
{
callLazyConstructor();
super.update (g);
}
/**
* Force the lazyConstructor() method implemented in the child class
* to be called. If this method is called more than once on
* a given object, all calls but the first do nothing.
*/
public synchronized final void callLazyConstructor()
{
// The general idea below is as follows:
// 1) See if this method has already been successfully called.
// If so, return without doing anything.
//
// 2) Otherwise ... call the lazy constructor.
// 3) Call validate so that any components added are visible.
// 4) Note that we have run.
if ((lazyConstructorCalled == false) && (getParent() != null))
{
lazyConstructor();
lazyConstructorCalled = true;
validate();
}
}
/**
* This method must be implemented by any child class. Most of
* the component creation code that would have gone in the constructor
* of the child goes here instead. See the example
* at the top.
*/
abstract protected void lazyConstructor ();
}
Using the LazyPanel
Using the LazyPanel class is straightforward, but there are a few things of which you should be aware.
Don't throw exceptions from lazyConstructor
For panels, it is easy enough to write constructors that throw exceptions if something goes wrong. Unfortunately, lazyConstructor is an ordinary method and not a constructor. Because lazyConstructor is called from paint() , it cannot throw anything except RuntimeExceptions and Errors . Since there isn't any caller other than the AWT thread to catch these exceptions and errors, it is best not to throw any exceptions at all. If necessary, place the body of your lazyConstructor method in a try/catch block and do something sensible in the catch block.
GUI builders will not cooperate
The code generated by the GUI builders in Inprise's JBuilder and Symantec's Cafe does not work well with the LazyPanel class. The GUI builders' generated code uses initializers to construct most of the GUI components for the panel. This eliminates the advantage of the LazyPanel , since none of the work is moved to the lazyConstructor() method.
One approach is to manually move the component construction from the initializers to the lazyConstructor method. Unfortunately, the GUI builder then can no longer modify the panel for further enhancements. A better approach is to keep the GUI-builder-generated panel unmodified and put it inside a LazyPanel . The LazyPanel then contains only one component -- the component built by the GUI builder.
Your code will not perform any faster in the long run
Finally, this approach doesn't actually speed up your application. If your GUI originally needed 1 MB of memory and took 30 seconds to create all the components, it will still need 1 MB of memory and will still take 30 seconds to fully construct. The LazyPanel spreads the cost of constructing the needed GUI components over time, so you pay the price in small chunks instead of requiring all the memory and time up front. LazyPanel does not, however, do anything to reduce that cost. Often this class will be good enough to accelerate your GUI. Other times, however, simply dropping in a LazyPanel or two will only begin your serious performance tuning.
Conclusion
Java GUIs with many components initialize more quickly by completing only the absolute minimum initialization necessary. The LazyPanel class lets you speed up the initialization of more complex GUIs with little extra programming. It is a good start for improving the speed of complex GUIs and often is sufficient for less complicated ones.
This page formated for crawlers and browsers that
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: Java Tip 90: Accelerate your GUIs -
JavaWorld
View Tutorial: Java Tip 90: Accelerate your GUIs -
JavaWorld
Related
Tutorials:
Reloading Applets
Reloading Applets |
Applet to Applet
Communication
Applet to Applet
Communication |
Java Tip 72: Press
Escape to close your Swing dialog windows
Java Tip 72: Press
Escape to close your Swing dialog windows |
Enhance your Java application with Java Native Interface (JNI)
Enhance your Java application with Java Native Interface (JNI) |
Flex your grid
layout
Flex your grid
layout |
Trace your steps in Java 1.4
Trace your steps in Java 1.4 |
Make a statement with javac!
Make a statement with javac! |
Quickly access files and
directories you use repeatedly
Quickly access files and
directories you use repeatedly |
Java Tip 132: The
taming of the thread
Java Tip 132: The
taming of the thread |
roots of
constants classes
roots of
constants classes |
Profiling the
profilers
Profiling the
profilers |
Java Tip 143: Utilize
the Database Schema
Browser
Java Tip 143: Utilize
the Database Schema
Browser |
Java and Sound, Part 1
On systems that support it, sound can be an important part of many applications. Sound can be used to notify the user that her attention is required, to add the extra dimension of aural feedback to visual GUIs, or for entertainment purposes. |
SpeedJG - XML Builder
SpeedJG - XML based Java Swing GUI Builder |
Filtering and Transforming Digital Images
Filtering and Transforming Digital Images
In this Issue
Welcome to the Core Java Technologies Tech Tips for April 7, 2004. Here you\'ll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
|
Wi.Ser (WidgetServer) unified rich client framework
Wi.Ser is a Java/XML server-side GUI-framework which enables an application to run as either a monolithic Swing application, a thin-client/server Swing application, or as a Web application without any change!
|
Tech Tip: Using the Varargs Language Feature
Have you ever needed to pass in many instances of the same object type to a method, but you don't know at compile time how many instances there will be? Find out how the new varargs language feature makes it easy to handle situations like this. |
Open Source Web Frameworks in Java
Open Source Web Frameworks in Java
Open Source Web Frameworks in Java
Struts
Struts Frame work is the implementation of Model-View-Controller (MVC) design pattern for the JSP. Struts is maintained as a part of Apache Jakarta project and is open |
Welcome to Free search engine secrets: webmaster's guide to search engine
registration!
Welcome to Free search engine secrets: webmaster's guide to search engine registration!
Welcome To Webmaster's Guide
T his site is dedicated to Web related services. Here you can find tools and suggestions to promote your sites to several search |
Sanssouci is a Java framework for autogenerating fancy Swing-GUIs via introspection.
Sanssouci is a Java framework for autogenerating fancy Swing-GUIs via introspection which display objects directly to the user |
|
|
|