First, the border reverses. By being white on the left and top, black on the other sides, the button appears raised, as if it were lighted from the top-left corner. Simply reversing these colors makes the button appear to go in and out of the page. But that's not all.
The extra trick to making a really "clicky" button is moving the text one pixel down and right when the button is punched. (Going two pixels looks great at first, but it wears thin very quickly.)
Try the Swing button and then click the RButton to see the difference. Of course, the vertical RButtons are going in a direction that Swing doesn't match. See the Command Bars example for one useful application for a vertical button.
You can use the BorderFactory, but I prefer to draw my own for complete control. The demo here uses white and black borders, but if you study my Application Framework carefully (use your largest monitor at its lowest resolution) you'll see that I use multiple colors for a more rounded look.
The buttons here use the default font, which is Dialog, bold, for the JButton (and most other Swing components), but is Dialog, plain, for the JComponent (the RButton's superclass).
Click the "Documentation" or "Source code" links (on the left) to view all the javadoc and source code. This applet is ButtonDemo. All applets are in the applets package. The RButton is a widget in the widgets package.
int offset = isDown ? 1 : 0;
g.drawString( text, x + offset, y + offset );
Drawing the borders isn't exactly rocket science, either. The only wrinkle is that you have to be very careful about where you start and end the lines, as this drawing shows.
private void paintUpDown( Graphics g ) {
int right = getWidth() - 1;
int bottom = getHeight() - 1;
g.setColor( isDown ? Color.BLACK: Color.WHITE );
g.drawLine( 0, 0, right, 0 );
g.drawLine( 0, 1, 0, bottom );
g.drawLine( 1, 1, right-1, 1 );
g.drawLine( 1, 2, 1, bottom-1 );
g.setColor( isDown? Color.WHITE: Color.BLACK );
g.drawLine( 1, bottom, right, bottom );
g.drawLine( 2, bottom-1, right-1, bottom-1 );
g.drawLine( right-1, 2, right-1, bottom-2 );
g.drawLine( right, 1, right, bottom - 1 );
} // end of paintBorder()
Standing on its side takes a little bit of Graphics2D coding. The rotation is simple (except for the annoying shift from degrees to radians, which I always forget). The tricky bit is that the rotation is around the Graphics' origin. You have to move 0,0 from the upper-left corner to the left edge of the text's baseline. This is the method in the RButton class:
private void paintTextVertical( Graphics g ) {
int width = getWidth();
int height = getHeight();
String text = getText();
// String size
FontMetrics fm = g.getFontMetrics();
int shgt = fm.stringWidth( text );
int swid = fm.getHeight();
int x = (width-swid)/2 + fm.getAscent();
int y = (height - shgt)/2 + shgt;
Graphics2D g2d = (Graphics2D) g;
g2d.translate( x, y );
g2d.rotate( Math.toRadians(-90) );
g2d.setColor( getForeground() );
int offset = isDown ? 1 : 0;
g2d.drawString( text, offset, offset );
} // end of paintTextVertical()