23.3 HTML and JEditorPane


As we discussed in Chapter 19, Swing provides (somewhat spotty) support for working with the Web's most common markup language, HTML. Fortunately, as Swing matures, the HTML support in the JEditorPane class improves.

The support for reading, writing, and displaying HTML through the JEditorPane class is provided by the HTMLEditorKit and associated classes. This class is an extension of the generic DefaultEditorKit class and is devoted (not surprisingly) to HTML files. You might recall from the previous discussion of EditorKit that there are three basic parts of an editor kit: its parser, its file writer, and its association with a ViewFactory. While we have looked briefly at these pieces before, here we focus on their implementation in HTMLEditorKit.

Along the way, we'll see how to extend some of these pieces to do custom work in the context of an HTML document. We decided that a detailed discussion of the classes that extend the editor kit would not be interesting to a majority of our readers, so we concentrate on the more immediately useful classes. However, if you want to see the details and play with the internals of the HTMLEditorKit, we have two entire chapters devoted to this topic on the book's web site (http://www.oreilly.com/catalog/jswing2). Throughout this discussion, we'll point you to that material if you want more detail than we've provided here.

Much of the information in those chapters describes how you can extend HTML with custom tags. Adding custom tags to HTML is not really a good idea in most cases. You are better off using XML, which is by definition extensible, for that purpose. A great book to start with is Java and XML by Brett McLaughlin from O'Reilly, of course.

If you're just looking for basic HTML editing and rendering, you'll be in good shape after reading the rest of this chapter. If you need to support custom tags or write your own ViewFactory, grab the online chapters.

23.3.1 A Quick Browser Example

Before we get down to business on the API, here's an example of the HTMLEditorKit's power. In a very small amount of code, we can create a web browser. This minibrowser contains nothing more than two labels, a text field, and a JEditorPane controlled by the HTMLEditorKit. The browser is similar to the very first example in this chapter, but we've added the ability to enter URLs, and we show the destination URL in the status bar whenever you mouse over a hyperlink. (We also added support for hyperlinks inside HTML frames.)

We'll cover all the parts in more detail, but if you can't wait to get started with your own browser, pay special attention to the SimpleLinkListener.java file. That's where most of the real work in this example occurs.[7] If all you need to do is display HTML text in your application, this is the example to look at (or perhaps the even simpler one at the start of the chapter).

[7] The original version of this browser appeared in Marc's article, "Patch the Swing HTMLEditorKit," JavaWorld, January 1999 (http://www.javaworld.com/javaworld/jw-01-1999/jw-01-swing.html). Our derivative code is used with permission. Thanks also to Mats Forslöf (at Marcwell, in Sweden) for his improvements to the original version. Feel free to check out the article, but be aware that the patch mentioned fixes a pre-1.3 bug.

Here's the code for this mini-browser. The first file, MiniBrowser.java, sets up the basic Swing components you can see in Figure 23-6, namely a text field for entering new URLs, a JEditorPane for displaying the current page, and a label at the bottom of the frame to function as the status bar. (The status bar reflects the "go to" URL when you place your mouse cursor over a hyperlink.) The second file, SimpleLinkListener.java, handles the hyperlink events.

Figure 23-6. MiniBrowser on a Mac OS X system displaying www.oreilly.com
figs/swng2.2306.gif
// MiniBrowser.java // import javax.swing.*; import javax.swing.text.*; import java.awt.event.*; import java.awt.*; import java.io.File; public class MiniBrowser extends JFrame {   private JEditorPane jep;   public MiniBrowser(String startingUrl) {     // First, just get a screen up and visible, with an appropriate handler in place     // for the kill window command.     super("MiniBrowser");     setSize(400,300);     setDefaultCloseOperation(EXIT_ON_CLOSE);     // Now set up our basic screen components, the editor pane, the text field for     // URLs, and the label for status and link information.     JPanel urlPanel = new JPanel( );     urlPanel.setLayout(new BorderLayout( ));     JTextField urlField = new JTextField(startingUrl);     urlPanel.add(new JLabel("Site: "), BorderLayout.WEST);     urlPanel.add(urlField, BorderLayout.CENTER);     final JLabel statusBar = new JLabel(" ");     // Here's the editor pane configuration. It's important to make the     // "setEditable(false)" call; otherwise, our hyperlinks won't work. (If the text     // is editable, then clicking on a hyperlink simply means that you want to change     // the text, not follow the link.)     jep = new JEditorPane( );     jep.setEditable(false);     try {       jep.setPage(startingUrl);     }     catch(Exception e) {       statusBar.setText("Could not open starting page.  Using a blank.");     }     JScrollPane jsp = new JScrollPane(jep);      // Get the GUI components onto our content pane.     getContentPane( ).add(jsp, BorderLayout.CENTER);     getContentPane( ).add(urlPanel, BorderLayout.NORTH);     getContentPane( ).add(statusBar, BorderLayout.SOUTH);     // Last but not least, hook up our event handlers.     urlField.addActionListener(new ActionListener( ) {       public void actionPerformed(ActionEvent ae) {         try {           jep.setPage(ae.getActionCommand( ));         }         catch(Exception e) {           statusBar.setText("Error: " + e.getMessage( ));         }       }     });     jep.addHyperlinkListener(new SimpleLinkListener(jep, urlField, statusBar));   }   public static void main(String args[]) {     String url = "";     if (args.length == 1) {       url = args[0];       if (!(url.startsWith("http:") || url.startsWith("file:"))) {         // If it's not a fully qualified URL, assume it's a file.         if (url.startsWith("/")) {           // Absolute path, so just prepend "file:"           url = "file:" + url;         }         else {           try {             // Assume it's relative to the starting point.             File f = new File(url);             url = f.toURL( ).toString( );           }           catch (Exception e) {             url = "http://www.oreilly.com/";           }         }       }     }     else {       url = "http://www.oreilly.com/";     }     new MiniBrowser(url).setVisible(true);   } } 

Here's SimpleLinkListener.java. Notice that the "entered" and "exited" event handlers do not bother with the mouse cursor. As of SDK 1.3, the mouse cursor is automatically updated as you enter and exit hyperlinks. All we do is update the status bar. Don't worry too much about the hyperlink handling; we'll tackle that topic in the next section. We hope that you have seen enough event-handling code in Java to find this class familiar without reading the details yet.

// SimpleLinkListener.java // A hyperlink listener for use with JEditorPane. This listener changes the cursor // over hyperlinks based on enter/exit events and also loads a new page when a valid // hyperlink is clicked. import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.text.html.*; public class SimpleLinkListener implements HyperlinkListener {   private JEditorPane pane;       // The pane we're using to display HTML   private JTextField  urlField;   // An optional text field for showing the current                                   // URL being displayed   private JLabel statusBar;       // An optional label for showing where a link would                                  // take you   public SimpleLinkListener(JEditorPane jep, JTextField jtf, JLabel jl) {     pane = jep;     urlField = jtf;     statusBar = jl;   }   public SimpleLinkListener(JEditorPane jep) {     this(jep, null, null);   }   public void hyperlinkUpdate(HyperlinkEvent he) {     HyperlinkEvent.EventType type = he.getEventType( );     if (type == HyperlinkEvent.EventType.ENTERED) {       // Enter event. Fill in the status bar.       if (statusBar != null) {         statusBar.setText(he.getURL( ).toString( ));       }     }     else if (type == HyperlinkEvent.EventType.EXITED) {       // Exit event. Clear the status bar.       if (statusBar != null) {         statusBar.setText(" "); // Must be a space or it disappears       }     }     else if (type == HyperlinkEvent.EventType.ACTIVATED) {       // Jump event. Get the URL and, if it's not null, switch to that page in the       // main editor pane and update the "site url" label.       if (he instanceof HTMLFrameHyperlinkEvent) {         // Ahh, frame event; handle this separately.         HTMLFrameHyperlinkEvent  evt = (HTMLFrameHyperlinkEvent)he;         HTMLDocument doc = (HTMLDocument)pane.getDocument( );         doc.processHTMLFrameHyperlinkEvent(evt);       } else {         try {           pane.setPage(he.getURL( ));           if (urlField != null) {             urlField.setText(he.getURL( ).toString( ));           }         }         catch (FileNotFoundException fnfe) {           pane.setText("Could not open file: <tt>" + he.getURL( ) +                         "</tt>.<hr>");         }         catch (Exception e) {           e.printStackTrace( );         }       }     }   } }


Java Swing
Graphic Java 2: Mastering the Jfc, By Geary, 3Rd Edition, Volume 2: Swing
ISBN: 0130796670
EAN: 2147483647
Year: 2001
Pages: 289
Authors: David Geary

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net