HTML Labeled Components

One of the coolest yet little known features of the Java Foundation Classes (aka Swing) is the ability to label components with HTML. For example, let’s suppose you want a button that contains both bold and non-bold text on separate lines like this:

Button text: Damn the Torpedoes! Full speed ahead!

This is quite complex to implement in Java code. You have to subclass JButton, override paint(), and perform many detailed calculations with FontMetrics objects just to decide where to draw the different text strings. On the other hand, it’s straight-forward code this in HTML:

<html><b><font size=+2>Damn the torpedoes!<br><i>Full speed ahead

Starting in JFC 1.1.1, you don’t have to put yourself through the pain of calculating exactly where to draw the different text strings. Instead you can simply label the button with the HTML like this:

JButton bigButton = new JButton( "<html><b><font size=+2>Damn the torpedoes!<br><i>Full speed ahead!" ));

That’s it. Once it’s constructed, you just use the button like normal. Java recognizes the <html> tag and renders the HTML you’ve placed on the button.

Some older version of Java and Swing do not recognize the equivalent uppercase tag <HTML>. For reasons I’ve never understood, Sun has had a grudge against upper case HTML tags going way back to HotJava 1.0alpha1. It will recognize other uppercase HTML tags like <B> and <CITE>, but the <html> tag itself must be lowercase.

The same trick works for JLabel, JTabbedPane, JMenuItem, and JToolTip. Java 1.4 and later also support HTML in JRadioButton and JCheckBox.

HTML is particularly appropriate for labels. HTML makes multiline, word-wrapped, styled labels a snap to code. For example, suppose you want to include an ordered list in a dialog box or form like this:

When filling out the form, please observe these rules: Write in the third person Use complete sentences Check your spelling and grammar before submitting Do not abbreviate Leave fields that do not apply to you blank. Do not write "N/A" or "not available". Remember, the more editing that's required the longer it will be before your submission is posted.

Here’s all you have to do:

    JLabel l = new JLabel("<html>When filling out the form, please observe these rules: "
     + "<ul>"
     + "<li>Write in the <em>third</em> person"
     + "<li>Use complete sentences"
     + "<li>Check your spelling and grammar before submitting"
     + "<li>Do <strong>not</strong> abbreviate"
     + "<li>Leave fields that do not apply to you blank. "
     + "Do not write &quot;N/A&quot; or &quot;not available&quot;."
     + "</ul>"
     + " Remember, the more editing that's required the longer "
     + " it will be before your submission is posted.");

That’s much easier than trying to get the same effect by making multiple calls to drawString() in a paint() method with different coordinates derived from the font metrics. It’s more attractive than you could get with a TextArea or a JTextArea. The only other classes that are really competitive with this label are JEditorPane and JTextPane, but they don’t fit into the user interface form as neatly, and are more intended to be used as the main focus of a program rather than just a part of a larger picture.

Java supports almost all of HTML 3.2 including paragraphs, lists, images, horizontal rules, tables, entity references like &lt;, and even CSS Level 1. What’s not supported are image maps, frames, and applets. In addition a few elements are rendered but do not behave as you might expect. For example, links inserted with the <a> tag are blue and underlined, but clicking on them doesn’t take you anywhere. Forms and buttons are displayed, but users can’t interact with them. The img element is supported, but the URL it uses for its src attribute must be an absolute URL like http://www.fatbrain.com/graphics/navbar/fblogo_184x61.gif instead of a relative URL like /graphics/navbar/fblogo_184x61.gif or fblogo_184x61.gif. That’s because there’s no underlying document for the relative URL to be relative to. The bgcolor and text attributes of the body element are ignored. Otherwise, everything else you might want is available. HTML on labels, buttons, and other components isn’t a replacement for a web browser, but it is more than adequate for adding style to your user interfaces.

Further reading:

The URL and URLConnection classes used in the sample program are discussed in my own Java Network Programming. The original file-based program that alerted me to the need for some sort of progress bar is developed starting in Chapter 4 of Java I/O and continued throughout the book. Java I/O also discusses the general behavior of input streams and filter input streams like ProgressMonitorInputStream in great detail.

The importance of providing users with feedback is elucidated in any good text on user interface design. However, one of the most readable is Bruce Tognazzini’s Tog on Interface.

The ProgressMonitor and ProgressMonitorInputStream classes themselves are discussed in Chapter 9 of John Zukowski’s Definitive Guide to Swing for Java 2.

One Response to “HTML Labeled Components”

  1. jimthev Says:

    Active buttons in JEditorPane

    To make active buttons in html rendered by a JEditorPane, we override the method:

    public View create(Element elem) {

    in the class HTMLEditorKit.HTMLFactory to return our own FormView for buttons.

    This FormView subclass overrides:

    protected Component createComponent() {

    To return our own Components based on the HTML.Attribute.NAME attribute of the Element.

    For all this to work, we had to subclass JEditorPane, and HTMLEditorKit to get the our new classes to be called, but once you know that the individual components are created in the above referenced methods, the work is basically done. A similar technique is probably possible for all HTML Labeled Components.