August 28, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Unique GUI Components, Part 2: Panel, Progress Bar, Label, Image, and Line

  • September 27, 2000
  • By Chunyen Liu
  • Send Email »
  • More Articles »

In Part 1 Unique GUI Components, Part 1: Text-based and Image-based Buttons , we presented two types of buttons and described in detail how to make them from scratch. As we also mentioned before, most browsers still do not support the powerful Java 2 Swing classes offered by the standard JDK package; thus, additional downloads and installations are required to use those new features. Furthermore, Java 2 slows down applet loading and execution within browsers. For lots of simple applets, some basic GUI components will do the trick. In these tutorials, we hope to spice up the basic AWT component classes without making them grow out of proportion.

Our intention here is not to rewrite all the AWT component classes, but to provide some fundamental knowledge, with examples, for you in case you are one of those people who want to know every little detail or are enthusiastic about making a one-of-a-kind user interface. Your own GUI components do have the advantage of maintaining the same look and feel on different platforms. Not until Java 1.2 Swing becomes widely adopted will the standard JDK have a consistent look and feel on different JVM implementations.

This time we will cover group panel, line separator, label, image canvas, and progress bar. In order to make this article stay within a reasonable length, we mainly focus on those features we probably want to put in with little effort. Please refer to the source code for more details. For example, instead of going through every feature a standard label already has, we only talk about how to add a background image to it. No doubt you can always come up with much more attractive results using your own artistic creativity, which is one of the many things I lack talent in.

All of the GUI components mentioned in this article are put together in one example. All of them are demonstrated live. Each will be described later. The source code files used in this article are: gui2_ex.java , gui2_ex.html , gui2_myPanel.java , gui2_myProgressBar.java , gui2_myLine.java , gui2_myLabel.java , and gui2_myImage.java .

Live example 3.

Group Panel

We are going to add more features to the standard AWT Panel class. There are several possibilities, but we describe two options as in our demonstration. First, what about having a cool background image? In the example, the embossed author image is tiled throughout the entire panel. This can be easily done by redrawing the image with width and height offsets. Second, wouldn't it be nice to have a group panel title surrounded by a bounding box? We need to measure the font metrics in order to draw the top line of the bounding box. We also need to erase the extra lines with background color where the title string will be drawn. Buttons 1 and 2 are simply used to illustrate the combining use of regular AWT GUI components with our home-grown classes.

public void paint(Graphics g)
   {
   // lay out the background image if any
   if (withBGImage)
      {
      for (int y = 0; y < height - 1; y += hh)
         for (int x = 0; x < width - 1; x += ww)
            g.drawImage(image, x, y, this);
      }

   int w1 = (g.getFontMetrics()).stringWidth(title);
   int h1 = (g.getFontMetrics()).getHeight();
   int d1 = (g.getFontMetrics()).getDescent();

   // draw the bounding box
   g.setColor(white2);
   g.drawRect(5, h1 / 2 + 1, width - 10, height - h1 - d1 - 5);
   g.setColor(black2);
   g.drawRect(4, h1 / 2, width - 10, height - h1 - d1 - 5);

   // erase the extra lines
   g.setColor(getBackground());
   g.drawLine(12, h1 / 2, 12 + w1 + 3, h1 / 2);
   g.drawLine(12, h1 / 2 + 1, 12 + w1 + 3, h1 / 2 + 1);

   // draw the title string
   g.setColor(white2);
   g.drawString(title, 16, h1);
   g.setColor(black2);
   g.drawString(title, 15, h1 - 1);
   }

Progress Bar

For a lengthy operation, an hourglass or a progress bar usually helps users to visualize the finished percentage of the task or lessen the waiting anxiety, to say the least. We put in both bar rectangle and digits to indicate the progress. To protect the digits from being overdrawn by the filled rectangle, we make them hollow by coloring the four corners in foreground color and digits themselves in background color. For more tricks like this, check out the article I wrote for JavaWorld in the references.

public void paint(Graphics g)
   {
   if (raised)
      {
      g.setColor(getBackground().brighter());
      g.drawLine(0, 0, width - 1, 0);
      g.drawLine(0, 0, 0, height - 1);
      g.setColor(getBackground().darker());
      g.drawLine(0, height - 1, width - 1, height - 1);
      g.drawLine(width - 1, 0, width - 1, height - 1);
      }
   else
      {
      g.setColor(getBackground().darker());
      g.drawLine(0, 0, width - 1, 0);
      g.drawLine(0, 0, 0, height - 1);
      g.setColor(getBackground().brighter());
      g.drawLine(0, height - 1, width - 1, height - 1);
      g.drawLine(width - 1, 0, width - 1, height - 1);
      }

   g.setFont(new Font("Helvetica", Font.BOLD, 12));
   String s = percent + "%";

   // fill in bar color proportionally
   g.setColor(bg);
   g.fillRect(1, 1, width - 2, height - 2);
   g.setColor(fg);
   g.fillRect(1, 1, width * percent / 100, height - 2);

   int w = (width - (g.getFontMetrics()).stringWidth(s)) / 2;
   int h = (g.getFontMetrics()).getHeight();
   int myd = (g.getFontMetrics()).getDescent();
   h += ((height - h) / 2 - myd);
 
   // make a hollow string
   g.drawString(s, w - 1, h);
   g.drawString(s, w + 1, h);
   g.drawString(s, w, h - 1);
   g.drawString(s, w, h + 1);
   g.setColor(bg);
   g.drawString(s, w, h);
   }

Line Separator

A line separator is usually useful to divide components into groups horizontally or vertically. To add a little bit of 3D flavor, we employ two styles: raised and embossed. It is all illusion, because most people assume the light comes from the top. In fact, we use the same trick in other components as well (e.g., group panels, buttons). w and h are the width and height of the line. start and end are the terminal coordinates for the line.

if (horizontal)
   {
   if (raised)
      {
      g.setColor(getBackground().brighter());
      g.drawLine(start, h / 2 - 1, end, h / 2 - 1);
      g.setColor(getBackground().darker());
      g.drawLine(start, h / 2, end, h / 2);
      }
   else
      {
      g.setColor(getBackground().brighter());
      g.drawLine(start, h / 2, end, h / 2);
      g.setColor(getBackground().darker());
      g.drawLine(start, h / 2 - 1, end, h / 2 - 1);
      }
   }
else
   {
   if (raised)
      {
      g.setColor(getBackground().brighter());
      g.drawLine(w / 2 - 1, start, w / 2 - 1, end);
      g.setColor(getBackground().darker());
      g.drawLine(w / 2, start, w / 2, end);
      }
   else
      {
      g.setColor(getBackground().brighter());
      g.drawLine(w / 2, start, w / 2, end);
      g.setColor(getBackground().darker());
      g.drawLine(w / 2 - 1, start, w / 2 - 1, end);
      }
   }

Label

In a regular JDK label, we usually have these attributes to choose from: alignment, text, background color, foreground color, font. Since we extend the label from Canvas, we need to measure the font metrics in order to align the text. Adding an image background is similar to what we have seen in the group panel implementation.

public void paint(Graphics g)
   {
   if (background != null)
      {
      for (int y = 0; y < height - 1; y += hh)
         for (int x = 0; x < width - 1; x += ww)
            g.drawImage(background, x, y, this);
      }
   else
      {
      g.setColor(bc);
      g.fillRect(0, 0, width, height);
      }

   int myy = (g.getFontMetrics()).getHeight();
   int myd = (g.getFontMetrics()).getDescent();
   int myw = (g.getFontMetrics()).stringWidth(label);
   g.setColor(fc);

   // alignment: (0 = left, 1 = center, 2 = right)
   if (align == 0)
      g.drawString(label, 1, height / 2 + myy / 2 - myd);
   else if (align == 1)
      g.drawString(label, Math.max(width / 2 - myw / 2, 1), height / 2 + myy / 2 
         - myd);
   else
      g.drawString(label, Math.max(width - myw - 1, 1), height / 2 + myy / 2 - myd);
   }

Image Canvas

In Part 1, we made our image button from an AWT Canvas class. An image canvas is a container for an image and is almost identical to an image button, except that it does not need to respond to regular mouse actions. Of course, you can still touch it up a little (e.g., borders).

public void paint(Graphics g)
   {
   g.drawImage(image, 0, 0, this);
   if (style == 1)
      {
      g.setColor(white2);
      g.drawRect(offset, offset, width - 1 - 2 * offset, height - 1 - 2 * offset);
      }
   else if (style == 2)
      {
      g.setColor(black2);
      g.drawRect(offset, offset, width - 1 - 2 * offset, height - 1 - 2 * offset);
      }
   }

Conclusion

In these two tutorial articles on GUI components, we have covered text button, image button, group panel, line separator, label, image canvas, and progress bar. There are still a few components we did not investigate (e.g., tab, slide bar). However, the main purpose of these discussions is to give you an idea as to how you can improve or create your own GUI components. I believe many of you have more of these basic skills than I do, so no doubt you can definitely do a much better job with these than I've done.

References

  1. Ken Arnold and James Gosling, The Java Programming Language, Addison-Wesley, 1997.
  2. Jerry Jackson and Alan McClellan, Java by Example, Sun Microsystems Press, 1999.
  3. Rich Kadel, "Learn how to extend the AWT with your own image buttons," JavaWorld, March 1997.
  4. Chunyen Liu, "Java Tip 81: Jazz up the standard Java fonts," JavaWorld, November 1999.

About the Author

About the Author

Chunyen Liu has been with the engineering department at a world's leading GPS company for a while. Some of his applications were among winners at programming contests administered by SUN, ACM, and IBM. He also had co-authored U.S. patents and written articles for various publishers. He holds advanced degrees in computer science and operates a hobby site called The J Maker. On the non-technical side, he is a tournament-rated table tennis player, certified umpire, and certified coach of USA Table Tennis.






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel