JEditorPane

1. JEditorPane: Basics

JEditorPane is sort of a fancy text area that can display text derived from different file formats. The built-in version supports HTML and RTF (Rich Text Format) only, but you can build "editor kits" to handle special purpose applications. In principle, you choose the type of document you want to display by calling setContentType and specify a custom editor kit via setEditorKit. Note that unless you extend it, legal choices are "text/html" (the default), "text/plain" (which is also what you get if you supply an unknow type), and "text/rtf".

In practice, however, JEditorPane is almost always used for displaying HTML. If you have plain text, you might as well use JTextField. RTF support is pretty primitive. You put content into the JEditorPane one of four ways.

In principle, a JEditorPane can be editable, but in practice it tends to look pretty poor, so it is most often used simply to display HTML, and you call setEditable(false) on it. Finally, as with all Swing components, scrolling is realized by dropping it in a JScrollPane. Thus, here's the most common way you use JEditorPane:
String url = "http://host/path";
try {
  JEditorPane htmlPane = new JEditorPane(url);
  htmlPane.setEditable(false);
  someWindow.add(new JScrollPane(htmlPane);
} catch(IOException ioe) {
  System.err.println("Error displaying " + url);
}

2. Following Hypertext Links

In most cases, you use a non-editable JEditorPane to display HTML text. In such a case, you can detect when the user selects a link, can determine which link was selected, and can replace the contents of the JEditorPane with the document at the specified URL (by using setPage). To do this, attach a HyperlinkListener (notice that it is HyperlinkListener, not HyperLinkListener) via addHyperlinkListener, and implement the hyperlinkUpdate method to catch events. Once you get the event, you need to look up its specific type via getEventType and compare that to HyperlinkEvent.EventType.ACTIVATED. This last point was not needed in early releases of Swing, but as of Java 1.2, if you neglect it, then the link will be followed whenever the mouse simple moves over the link. Here is an example:
public class SomeWindow extends JFrame implements HyperlinkListener {
  private JEditorPane htmlPane;
  
  ...
  
  public void hyperlinkUpdate(HyperlinkEvent event) {
    if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
      try {
        htmlPane.setPage(event.getURL());
      } catch(IOException ioe) {
        // Some warning to user
      }
    }
  }
}

3. Implementing a Simple Web Browser

By adding a simple URL textfield to a JEditorPane that can display HTML and follow links, you have a simple but functioning Web browser.

3.1 Simple Browser: Source Code (Download source code)

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class Browser extends JFrame implements HyperlinkListener, 
                                               ActionListener {
  public static void main(String[] args) {
    if (args.length == 0)
      new Browser("http://www.apl.jhu.edu/~hall/");
    else
      new Browser(args[0]);
  }

  private JIconButton homeButton;
  private JTextField urlField;
  private JEditorPane htmlPane;
  private String initialURL;

  public Browser(String initialURL) {
    super("Simple Swing Browser");
    this.initialURL = initialURL;
    addWindowListener(new ExitListener());
    WindowUtilities.setNativeLookAndFeel();

    JPanel topPanel = new JPanel();
    topPanel.setBackground(Color.lightGray);
    homeButton = new JIconButton("home.gif");
    homeButton.addActionListener(this);
    JLabel urlLabel = new JLabel("URL:");
    urlField = new JTextField(30);
    urlField.setText(initialURL);
    urlField.addActionListener(this);
    topPanel.add(homeButton);
    topPanel.add(urlLabel);
    topPanel.add(urlField);
    getContentPane().add(topPanel, BorderLayout.NORTH);

    try {
        htmlPane = new JEditorPane(initialURL);
        htmlPane.setEditable(false);
        htmlPane.addHyperlinkListener(this);
        JScrollPane scrollPane = new JScrollPane(htmlPane);
        getContentPane().add(scrollPane, BorderLayout.CENTER);
    } catch(IOException ioe) {
       warnUser("Can't build HTML pane for " + initialURL 
                + ": " + ioe);
    }

    Dimension screenSize = getToolkit().getScreenSize();
    int width = screenSize.width * 8 / 10;
    int height = screenSize.height * 8 / 10;
    setBounds(width/8, height/8, width, height);
    setVisible(true);
  }

  public void actionPerformed(ActionEvent event) {
    String url;
    if (event.getSource() == urlField) 
      url = urlField.getText();
    else  // Clicked "home" button instead of entering URL
      url = initialURL;
    try {
      htmlPane.setPage(new URL(url));
      urlField.setText(url);
    } catch(IOException ioe) {
      warnUser("Can't follow link to " + url + ": " + ioe);
    }
  }

  public void hyperlinkUpdate(HyperlinkEvent event) {
    if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
      try {
        htmlPane.setPage(event.getURL());
        urlField.setText(event.getURL().toExternalForm());
      } catch(IOException ioe) {
        warnUser("Can't follow link to " 
                 + event.getURL().toExternalForm() + ": " + ioe);
      }
    }
  }

  private void warnUser(String message) {
    JOptionPane.showMessageDialog(this, message, "Error", 
                                  JOptionPane.ERROR_MESSAGE);
  }
}
Note: also requires WindowUtilities.java and ExitListener.java, shown earlier, and JIconButton.java, shown later in this page.

3.2. Simple Browser: Sample Result

Simple Browser using JEditorPane

3.3 JIconButton: Source Code (Download source code)

This is a very simple image button with no borders, used in Browser.java.
import javax.swing.*;

public class JIconButton extends JButton {
  public JIconButton(String file) {
    super(new ImageIcon(file));
    setContentAreaFilled(false);
    setBorderPainted(false);
    setFocusPainted(false);
  }
}

HTML Support and JavaHelp

Although it is getting better, JEditorPane still only supports a subset of standard HTML. Many constructs cannot be displayed properly, and worse yet, many standard constructs crash the JEditorPane, generating long and ugly error messages. So although writing a simple browser is fun, it is risky in a real application to accept HTML input that you haven't tested previously. So perhaps the single best use of JEditorPane is to display non-editable HTML that you have written (and tested!), supplied as on-line help for your application. This is such a good idea that Sun has provided a small package called JavaHelp that helps in this regard by making an outline (displayed in a JTree), generating an index, and so forth. See the JavaHelp home page for more details.


This page is part of my Quick Swing Tutorial for AWT Programmers. © 1999 Marty Hall. All source code freely available for unrestricted use. Created for for work in the Research and Technology Development Center of the Johns Hopkins University Applied Physics Lab, for courses in the Johns Hopkins Part-Time MS Program in Computer Science, and for various industry seminars and Java short courses.