The Java Tutorials' Weblog
Reworking the IconDemo
During the JavaSE 6 update to the Swing Tutorial, a decision was taken to convert a number of the old applets to stand-alone applications. We also converted the majority of them to NetBeans projects.
I got to convert the IconDemoApplet. It used to look like this:
![]()
«IconDemoApplet»
I changed it into the IconDemo application, which now looks like this:
![]()
«IconDemoApp»
The IconDemo is now launched with Java™ Web Start—just click the “Launch” button below (you may need to download JDK 6). To compile and run the example yourself, consult the example index from the Swing Tutorial pages.
The first step was to replace the acquisition of the image files. In the applet, this was handled by the <applet> tag in our HTML code:
<applet code="IconDemoApplet.class" ... >
<param NAME="IMAGEDIR" VALUE="images">
<param NAME="IMAGE0" VALUE="stickerface.gif">
<param NAME="CAPTION0" VALUE="Sticker Face">
<param NAME="WIDTH0" VALUE="230">
<param NAME="HEIGHT0" VALUE="238">
...
</applet>
We replaced this with an embedded table pointing at the image files:
String myargs[] = {
"sunw01.jpg", "Original SUNW Logo", "300", "200",
"sunw02.jpg", "The Clocktower", "275", "220",
"sunw03.jpg", "Clocktower from the West", "268", "195",
"sunw04.jpg", "The Mansion", "315", "200",
"sunw05.jpg", "Sun Auditorium", "330", "205"
};
and a pre-defined directory:
String imagedir = "images/";
The next step was to design the application. Rather than working with the old applet code, I used the NetBeans GUI Builder.

«NetBeans detail (click for 1020×746 full screen) »
With the GUI Builder, I was able to create a clean symmetrical layout. I could have even placed the picture count, captionLabel, between the two buttons, nextButton and previousButton.
The usual working method of NetBeans and its GUI Builder is to create a java file for your layout and a seperate java file for your logic. This is a clean way to split your logic from your display. If I was creating the IconDemo from scratch, I would have elected to do it this way.
However, my task was to convert an existing applet into an application. I therefore took the source code that GUI Builder generated and cut and paste it back into the original applet code. I had to change a number of the extended paths NetBeans created (it uses the full path to the class it's calling rather than depending on the import statements at the top of the file—probably a wise design decision) to simpler paths, for example:
nextButton.setBorder(javax.swing.BorderFactory.createEtchedBorder());
to:
nextButton.setBorder(BorderFactory.createEtchedBorder());
Not a huge change, but one that makes my source a little easier to read.
The original applet code had a hand-created layout. I tried to take the NetBeans code to copy and paste into the structure provided, but it was too confusing to match too completely different coding methods. Instead, I simplified its generated paths then pasted the entire code block into place:
// Lay out the GUI (taken from NetBeans code)
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
.addComponent(numberLabel, GroupLayout.DEFAULT_SIZE, 438, Short.MAX_VALUE)
.addComponent(photographLabel, GroupLayout.Alignment.LEADING,
GroupLayout.DEFAULT_SIZE, 438, Short.MAX_VALUE)
.addComponent(captionLabel, GroupLayout.Alignment.LEADING,
GroupLayout.DEFAULT_SIZE, 438, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(previousButton, GroupLayout.PREFERRED_SIZE, 144,
GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 150,
Short.MAX_VALUE)
.addComponent(nextButton, GroupLayout.PREFERRED_SIZE, 144,
GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(captionLabel)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(photographLabel, GroupLayout.DEFAULT_SIZE, 308,
Short.MAX_VALUE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(numberLabel)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(nextButton, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(previousButton, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
pack();
Testing and debugging took only a short while (and most of my issues were the pre-release Java SE 6 version that's available for Mac OSX).
My concluding recommendations: don't do it this way. Instead, use the full power of NetBeans to both give you a clean layout and an environment within which to build and test your project.
Note: The photographs used in the
IconDemoapplication are copyright ©2006 spriggs.net and licenced under a Creative Commons Licence.
-- Grif Rosser
Posted at 07:45PM Jul 13, 2007 by The Java Tutorial Team | Comments[22]
Friday Jul 13, 2007
Posted by Jeff Dinkins on July 16, 2007 at 03:56 PM PDT #
Posted by fred on July 17, 2007 at 12:32 AM PDT #
Posted by Christian Beer on July 17, 2007 at 01:27 AM PDT #
Posted by Mikael Grev on July 17, 2007 at 01:49 AM PDT #
Posted by Mikael Grev on July 17, 2007 at 01:51 AM PDT #
Can I request you to avoid this over reliance on netbeans please ??
When i started java, i took tutorial because it was simple, and to the point. If somebody showed me this code, then i wouldn't have switched.
Posted by Viswanath on July 17, 2007 at 02:29 AM PDT #
Posted by guest on July 17, 2007 at 04:56 AM PDT #
Posted by Gili on July 17, 2007 at 06:16 AM PDT #
Posted by aberrant on July 17, 2007 at 07:01 AM PDT #
Weblogs: HK2 modules, Mac upgrade disaster, and I18N ResourceBundles
Featured Podcast: Loopt the Social Networking Application
Java Today: IDE Shootout reca...
Posted by Chris Adamson's Blog on July 17, 2007 at 08:03 AM PDT #
Among them:
* Very ugly GUI, violating Sun's own style guide, e.g. regarding the distance between components, usage of borders, etc.
* Hard-coded sizes in the layout. Bad, bad, bad, bad, bad.
* Requiring a special tool like NetBeans. I don't know if this is a fanboy or a political thing. Whatever it is, it is bad. Don't you have any professional educators at Sun who can tell you a little bit about pedagogic principles?
* Mishandling of text updates in an event handler. From http://java.sun.com/docs/books/tutorial/uiswing/examples/components/IconDemoProject/src/components/IconDemoApp.java
//User clicked either the next or previous button public void actionPerformed(ActionEvent e) { //Show loading message photographLabel.setIcon(null); photographLabel.setText("Loading image...");That text will not be shown right when set here! The comment is misleading. You are still in the EDT. updatePhotograph(Photo photo) later cancels the setting out, in case the program flow for already loaded images is used.
In case the loadImage() branch is used instead, the text will be rendered since the event handler returns. However, it should be the loadImage() method setting the text, and not preactively the actionPerformed() method. For symmetric reasons it should also be the done() method in loadImage() later canceling the message, instead of relying on the flow of execution in the invoked updatePhotograph()
This label display logic is very bad style at best. Such junk code should not be done in a tutorial. Yes, I consider it junk code, particularly for a tutorial. I would not even accept it in rushed production code.
* Unexplained optimization claims like
// When running using Java Plug-in, getResourceAsStream // is more efficient than getResourceand then incredibly complicating the code of createAppImageIcon() is also not beneficial in teaching people.
createAppImageIcon() could be a few easy to understand lines instead of the current mess:
ImageIcon i = null; URL url = new ... getResource(...); if(url != null) { i = new ImageIcon(url); } else { ...Oh, by the way, what is the point in making the method static?
Oh, oh, by the way, the usage of a fixed-size buffer which must match be large enough to hold the largest image is also extremely bad style.
* Nesting the Photo class inside class IconDemoApp also doesn't buy you anything.
* The writing style for the // comments is bad. This is typical for IDE-only users. In an IDE one can still read comments interspersed without visible separation into the code due to syntax highlighting. But they look very bad when one (a scholar ...) studies the code as-is. You really hate your scholars, do you? Instead of
Please write * Further, for $DEITY's sake use JavaDoc comments for commenting classes and fields. Please! Please demonstrate best practice, not sloppy 1337 5crip7 h4cking sty1e.I could go on for some time. But Sun hasn't cared for six major releases. Please let the examples be done by professionals, not by the intern. Please follow Sun's own rules (JavaDoc, GUI style guide, etc.). Please don't add optimizations if this isn't the point of the demo. Please get the code properly reviewed.
If not, then at least don't be surprised that there are so many badly done GUI applications out there and that so few people get Java GUI programming.
Demo code like this perverts the goal of the whole tutorial. Assuming of course the goal is to teach people proper Java GUI programming. The goal should not be to squeeze as many effects in as few lines of code as possible, or to get away with the most simple constructs that just happen to work accidentally.
Posted by Kauer on July 17, 2007 at 10:25 AM PDT #
Posted by Adam on July 17, 2007 at 12:12 PM PDT #
Posted by Jerry on July 18, 2007 at 07:29 AM PDT #
Posted by alskiontheweb on July 18, 2007 at 07:40 AM PDT #
Posted by Fred on July 18, 2007 at 03:23 PM PDT #
Posted by aberrant on July 19, 2007 at 12:33 PM PDT #
Posted by aberrant on July 19, 2007 at 12:33 PM PDT #
Hey, they were even willing to ship a completely broken widget in Java 6, one that is in Swing since Java 1.2, because they were to lazy to cut through the red tape to get a fix for something they broke into the code.
Or look at this "discussion". Do you see any reaction from Grif Rosser? Do you see a discussion? I don't. Six days and Mr. Rosser doesn't consider us worthy. This is so typical for them. They don't talk to mortals. All they do is to issue patronizing statements. Or look at the rejoicing in the first comment. One Sun Swing guy congratulating another Sun Swing guy for a job badly done. Boy are they full of it.
They don't care. They never did, they never will.
Posted by Kauer on July 19, 2007 at 12:33 PM PDT #
Posted by Viswanath on July 19, 2007 at 12:33 PM PDT #
Posted by Grif Rosser on July 23, 2007 at 01:47 PM PDT #
update to the Swing Tutorial, a decision was taken to convert a number
Posted by runescape money on November 10, 2007 at 06:39 PM PST #
It’s very good article. Great site with very good look and perfect information. I like it too.
Posted by gold price on June 03, 2008 at 07:56 AM PDT #