Building Reusable Java Widgets
For the sake of clarity in the examples, I have kept the graphics to a minimum and focused on the “nuts and bolts” of creating a reusable widget.
A note about style: I precede all of my instance variables with an underscore. Variables in upper case are class variables (static variables), and variables in lower case are generally temporary variables that have either been passed into the method or defined within the current block. Class and interface names always start with an upper case letter. Event classes always use “Event” as a suffix, and listener interfaces always have “Listener” for a suffix.
The first widget is a simple vertical separator. A separator should be familiar to HTML users; the <hr> tag creates a horizontal rule. Separators are used to separate groups of components. The vertical separator is a very simple widget. It does not need to interact with any other widgets or objects. It is simply a visual component. After a little thought I came to the conclusion that this widget should be created by specialization, specifically by subclassing the Canvas class. Canvas is a good choice here since the only duty of the vertical separator is to render itself on the screen. Separators generally have an etched look to them, as if they were carved into the screen.
To create the 3D effect of etching, draw two lines next to each other, one darker than the background, the other lighter. Here is a simple Java code fragment to create two vertical lines—one will appear etched, the other one raised. See Figure 5 for a picture of the two lines.
public void paint( Graphics g ) {
// draw a raised line
g.setColor( _light ) ;
g.drawLine( 5, 10, 5, 40 ) ;
g.setColor( _dark ) ;
g.drawLine( 6, 10, 6, 40 ) ;
// draw an etched line
g.setColor( _dark ) ;
g.drawLine( 25, 10, 25, 40) ;
g.setColor( _light ) ;
g.drawLine( 26, 10, 26, 40) ;
}

Figure 5. Etched and Raised Lines
Here is how I set the values of the two instance variables _light and _dark :
_light = getBackground().brighter().brighter() ; _dark = getBackground().darker().darker() ;
Setting the values relative to the background color rather than a hard-coded color makes the code more general. These lines will appear etched and raised regardless of the background color of the region in which they appear.
The vertical separator should fill its allocated space vertically and center in its space horizontally. Within the paint method you can determine the space that has been allotted and calculate its dimensions. Here is how I did it:
size = size() ; int length = size.height ; int yPosition = ( size.width )/2 ; g.setColor( dark ) ; g.drawLine( 0, yPosition, length, yPosition ) ; g.setColor( light ) ; g.drawLine( 0, yPosition+1, length, yPosition+1 );
Now, there is one more critical method we need to override. Remember that I have chosen to subclass Canvas. The Canvas class provides a default size of 0x0. This means that if the widget is laid out using its default size, it will not show up. To achieve a meaningful default size, you need to override the getPrefferedSize and getMinimumSize methods. I have chosen a region of 4x8 pixels for both its preferred size and its minimum size. Why did I choose 4x8? The separator has an actual width of 2 pixels. Setting its preferred width to 4 gives it a 1 pixel buffer on each side. The preferred height of 8 pixels is somewhat arbitrary—any value greater than 0 is acceptable, just so it is visible. Remember if the separator is used properly, the layout manager will grow its height to an appropriate value regardless of the preferred height.
You can see the completed VerticalSeparator class in Listing 1. Remember, we built the vertical separator to fill the vertical space that is allocated, so be sure to place it appropriately. The east and west portions of the border layout are guaranteed to be vertical regions. If the separator is placed in either of those regions, it will grow to fill the vertical region. If you place it in the north or south regions, it will be sized to its preferred height of 8 pixels, which may not be what you want. I recommend you read up on layout managers and how they respond to a widget's need to be sized. Some completely disregard preferred sizes. You can see an applet that uses the vertical separator in Figure 6.

Figure 6. The VerticalSeparator in Action
In this example I have introduced some fundamental concepts of drawing and sizing. The goal of the vertical widget is simply to make your GUI look better. This is a noble goal, but in the next few examples we are going to look at some harder working widgets that really earn their keep. Before looking at those widgets, here are a couple of challenges.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.
Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.
Sponsored by ActiveState
| Speed Up Your Web Site with Varnish | Jun 19, 2013 |
| Non-Linux FOSS: libnotify, OS X Style | Jun 18, 2013 |
| Containers—Not Virtual Machines—Are the Future Cloud | Jun 17, 2013 |
| Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer | Jun 12, 2013 |
| Weechat, Irssi's Little Brother | Jun 11, 2013 |
| One Tail Just Isn't Enough | Jun 07, 2013 |
- Speed Up Your Web Site with Varnish
- Containers—Not Virtual Machines—Are the Future Cloud
- Linux Systems Administrator
- Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer
- Senior Perl Developer
- Technical Support Rep
- Non-Linux FOSS: libnotify, OS X Style
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- RSS Feeds
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




22 min 34 sec ago
25 min 25 sec ago
34 min 32 sec ago
1 hour 4 min ago
3 hours 30 min ago
7 hours 29 min ago
8 hours 46 min ago
12 hours 17 min ago
15 hours 10 min ago
15 hours 36 min ago