Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Java Tip 109: Display images using JEditorPane

Modify the JEditorPane component to display images

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
You can use the current JEditorPane component to display HTML markup, but to perform more complicated tasks, JEditorPane needs some improvement. Recently, I had to build an XML form builder application. One necessary component was a WYSIWYG HTML editor that could edit the HTML markup content inside some of the XML tags. JEditorPane was the obvious Java component choice for displaying the HTML markup, because that functionality was already built into it. Unfortunately, when inserted into the HTML markup, JEditorPane could not display images with relative paths. For example, if the following image with a relative path was contained in an XML tag, it would not be displayed properly:

<html><img src="images\example.gif" width=200 
height=200></img>


Conversely, an absolute path would work (assuming that the given path and image really existed):

<html><img src="file:\\c:\images\example.gif" width=200 
height=200></img>


In my application, images were always stored in a subdirectory relative to the XML file's location. Hence, I always wanted to use a relative path. This article will explain why this problem exists and how to fix it.

Why does this happen?

Taking a closer look at the constructors for JEditorPane will help us understand why it cannot display images in relative paths.

  1. JEditorPane() creates a new JEditorPane.
  2. JEditorPane(String url) creates a JEditorPane based on a string containing a URL specification.
  3. JEditorPane(String type, String text) creates a JEditorPane that has been initialized to the given text.
  4. JEditorPane(URL initialPage) creates a JEditorPane based on a specified URL for input.


The second and fourth constructors initialize the object with a reference to a remote or local HTML file. An HTMLDocument is inside every JEditorPane, and its base is set to the base of the URL constructor parameter. JEditorPanes created using those constructors can handle relative paths, because the base of the HTMLDocument combines with the relative path to create an absolute path.

If the first constructor is used, displayed text must be inserted after the object is created. The third constructor accepts a String as content, but the base is not initialized. Because I wanted to obtain the HTML markup from an XML tag and not a file, I needed to use either the first or third constructor.

How do we fix the problem?

Before I continue, let's unveil and solve another smaller problem. The most obvious way to insert markup into the JEditorPane is to use the setText(String text). However, that method requires that you input the entire displayed markup every time you make a change. Ideally, the new tag(s) should be inserted into the existing text. You can use the following code to add the new markup:

private void insertHTML
  (JEditorPane editor, String html, int location)
                                 throws IOException {
  //assumes editor is already set to "text/html" type
  HTMLEditorKit kit =
    (HTMLEditorKit) editor.getEditorKit();
  Document doc = editor.getDocument();
  StringReader reader = new StringReader(html);
  kit.read(reader, doc, location);
}


Now, getting to the heart of the matter: How does JEditorPane render HTML? Each type of JEditorPane references both a Document and an EditorKit. When JEditorPane is set to type "text/html", it contains an HTMLDocument, which contains the markup and an HTMLEditorKit that determines which classes render each tag contained in the markup. Specifically, the HTMLEditorKit class contains an HTMLFactory inner class whose create(Element elem) method actually examines each separate tag. Here is the code from that factory class, which handles image tags:

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comments (3)
Login
Forgot your account info?

Louis Vuitton LouisBy Anonymous on November 8, 2009, 1:54 amLouis Vuitton Louis Vuitton Louis Vuitton Reade GM Louis Vuitton Bedford Louis Vuitton Brentwood GM Louis Vuitton Brentwood Pomme Louis Vuitton Houston Louis...

Reply | Read entire comment

Complex, but handyBy Anonymous on October 22, 2009, 5:38 amThanks, it came in handy, but it can be simplified a little. I'm working with JDK5.0, so my swing code is a little different, but I think this applies to yours...

Reply | Read entire comment

I think it is not necessaty to reinvent the wheelBy Anonymous on September 7, 2009, 4:02 amString path = "pathWhereTheImagesAre"; String text = "theHTMLText"; JTextPane jTextPane1; //and naturally create it with "text/html" content HTMLDocument htmlDoc...

Reply | Read entire comment

View all comments

Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources