JavaEnterprise JavaUnique GUI Components, Part 1: Text-based and Image-based Buttons

Unique GUI Components, Part 1: Text-based and Image-based Buttons

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

The graphical user interface (GUI) has been playing an important role in interacting between applications and users for years. Any software without elaborate GUI components is usually viewed as bad design with little market value. Okay, what are GUI components then? They are the usual items you have been using almost in every application nowadays: buttons, labels, canvases, sliders, progress bars, text fields, tabs, etc. You may ask, Why are they mostly in rectangular shape and gray in color? Can we change their properties? How?

If you are getting tired of seeing the same standard GUI components offered by Sun’s JDK package or simply curious about how those components are made, here is a short tutorial series with examples for you to create your own unique GUI components from scratch. Please keep in mind that in order for these components to function properly in most browsers, no Java Swing classes are used, nor event handlers after JDK 1.1, since most browsers do not support JDK 1.2.

In this article, buttons are described in detail in terms of component properties and event handling. Buttons are classified into two categories: text-based and image-based. The main issues in creating a button include button state, shape, border style, event handling, font style, size, color, and so forth.

As in all my previous articles, I will demonstrate these homegrown GUI components by working examples with their source code. That way, you can test them and make your own modifications. The source code files used in this article are:
gui1_myTextButton.java
,
gui1_ex1.java
,
gui1_ex1.html
,
gui1_myImageButton.java
,
gui1_ex2.java
, and
gui1_ex2.html
.

Text-based Buttons

I am going to draw my own button on a blank canvas by extending the AWT Canvas class. There are four button states to be included in our design: normal (0), over (1), clicked (2), and disabled (-1). When no interaction is happening to a button, it is in a normal state. When the user moves the mouse over the button, it is in an over state. A button is in a clicked state when it is, of course, pressed. When a button is in a disabled state, it will not respond to any user interaction until it is enabled again. We override disable() and enable() in the AWT Component class for disabling and enabling components to be consistent with all other AWT components.

public void disable()
{
status = -1;
super.disable();
repaint();
}

public void enable()
{
status = 0;
super.enable();
repaint();
}

In order to visualize these different states, a 3D border is raised when on “mouseover.” The button colors will be inversed when the mouse button is clicked and the 3D border is depressed. To represent the disabled state, we simply use the background color. Of course, we also should provide the parameters for better control on the button caption, colors, font, and dimension. Another interesting setup is the button shape. Although it can be any shape by defining button polygons, we only implement two options in this design: oval and round rectangle. Please note I put a white shadow shifted by 1 in the actual code.


// draw borders
if (shape == 1)
{
g.setColor(Color.white);
g.drawOval(1, 1, width – 2, height – 2);
g.setColor(Color.black);
g.drawOval(0, 0, width – 2, height – 2);
}
else
{
g.setColor(Color.white);
g.drawRoundRect(1, 1, width – 2, height – 2, 10, 10);
g.setColor(Color.black);
g.drawRoundRect(0, 0, width – 2, height – 2, 10, 10);
}

Okay, we are almost there. Now we can draw the buttons according to different button states. The final step is emulating the events issued by the button actions. Please pay particular attention to the mouseUp() event. The function call action() is propagated up to the component parents until the event is processed.


public boolean mouseExit(java.awt.Event e, int x, int y)
{
status = 0;
repaint();
return true;
}

public boolean mouseEnter(Event e, int x, int y)
{
status = 1;
repaint();
return true;
}

public boolean mouseDown(Event e, int x, int y)
{
status = 2;
repaint();
return true;
}

// trigger an action event when mouse is released
public boolean mouseUp(Event e, int x, int y)
{
if (inside(x, y))
{
status = 1;
repaint();
if (!action(e, e.arg))
{
Container par = getParent();
while ((par != null)&&(!par.action(e, e.arg)))
{
par = par.getParent();
}
}
}
return true;
}

The following live example of three text buttons illustrates our design. Text Button 3 is disabled.

Live example #1

Image-based Buttons

Our image button is also extended from the AWT Canvas class. Again we have four button states included in our design: normal (0), over (3), clicked (1), and disabled (2). When no interaction is happening to a button, it is in a normal state. When the user moves the mouse over the button, it is in an over state. The disabled state is handled almost exactly the same way as in text buttons, but we now need to make the image correspond to the disabled state. First of all, the image passed to the button is stored into a 1D array by PixelGrabber(). Then I average the red, green, blue channels and create a new black and white image by createImage() and MemoryImageSource().

// button in a disabled state
void disableButtonImage()
{
int index, R, G, B, v;
int [] data2 = new int[width * height];

for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { index = y * width + x; R = (data[index] & 0x00ff0000) >> 16;
G = (data[index] & 0x0000ff00) >> 8;
B = data[index] & 0x000000ff;
v = (R + G + B) / 3;
data2[index] = (new Color(v, v, v)).getRGB();
}
pic[2] = createImage(new MemoryImageSource(width, height, data2,
0, width));
}

When the button is pressed, I simply get the inverse values for red, green, blue channels and create a new image by createImage() and MemoryImageSource().

// button when pressed
void selectedButtonImage()
{
int index, R, G, B;
int [] data1 = new int[width * height];

for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { index = y * width + x; R = (data[index] & 0x00ff0000) >> 16;
G = (data[index] & 0x0000ff00) >> 8;
B = data[index] & 0x000000ff;
data1[index] = (new Color(255 – R, 255 – G, 255 – B)).getRGB();
}
pic[1] = createImage(new MemoryImageSource(width, height, data1,
0, width));
}

The following live example of three image buttons illustrates our design. The Apple button enables the caption. The Grape button is disabled.

Live example #2

Conclusion

In this article, two types of buttons — text-based and image-based — are described in detail and illustrated by working examples. If standard AWT GUI components offered by Sun’s JDK package do not satisfy you, this should be a good tutorial to get you started on making your own unique GUI components from scratch. These components can be used by applets or applications. However, to make sure they work in most browsers when used in applets, no new classes in JDK 1.1 or later versions are included in our design. Now it is your turn to put your artistic and technical expertise into action.

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

Chunyen Liu is a software engineer at GARMIN International — a global positioning company. Some of his 100-plus Java programs have won major programming contests. Check out his personal page for more details. He also owns an online Java site called The J Maker.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories