javaswingjtextpanehtmleditorkitbulletedlist

JTextPane - Bullet with HTMLEditorKit list not rendering correctly unless I do setText(getText()) and repaint


I have:

JTextPane jtextPane = new JTextPane();
jtextPane.setEditorKit(new HTMLEditorKit());
...

Then later I try to add an unordered list button to the toolbar such that the action is:

Action insertBulletAction = 
        HTMLEditorKit.InsertHTMLTextAction ("Bullets", "<ul><li> </li></ul>", 
                                            HTML.Tag.P, HTML.Tag.UL);
JButton insertBulletJButton = new JButton(insertBulletAction);

And this does include the proper code if I take a dump of the html that's generated. However it will be rendered really badly, as in not even close to reasonable as illustrated below:

snapshot of generated bullet

However if I do:

jtextPane.setText(jtextPane.getText());
jtextPane.repaint();

Then all is well. But if I don't do BOTH lines, then neither will work alone. I can also make it work by setting the text before I make the jtextPane visible.

This is really odd and I don't understand why I'd have to do a setText(getText()) followed by a repaint().

PS: This is very similar to this question: How to implement bullet points in a JTextPane? And it works except that it's not rendering correctly. I don't know if it has to do with HTMLEditorKit vs RTFEditorKit, but something i causing the rendering to fail. The html source code under is perfect...

PS2: This link is also very handy but it also didn't show a solution.

Update: Here is the full code as requested, but there isn't much else...

public static void main(String[] args)
{
    JFrame jframe = new JFrame();
    jframe.setSize(800, 600);
    jframe.setVisible(true);

    JTextPane jtextPane = new JTextPane();
    jtextPane.setEditorKit(new HTMLEditorKit());

    Action insertBulletAction = new HTMLEditorKit.InsertHTMLTextAction ("Bullets", 
                                    "<ul><li> </li></ul>", HTML.Tag.P, HTML.Tag.UL);
    JButton insertBulletJButton = new JButton(insertBulletAction);
    insertBulletJButton.setRequestFocusEnabled(false);

    jframe.setLayout(new BorderLayout());
    jframe.add(new JScrollPane(jtextPane));
    jframe.add(insertBulletJButton, BorderLayout.SOUTH);
}

Solution

  • The answer is actually quite complex. Basically the InsertHtmlAction is just not good enough by itself. You need a lot of work and logic to get to a working list action. It requires a lot of logic! So you definitely have to override the Action class. Basically the parameters of the InsertHtmlAction will change depending on where in the html code you are.

    That being said, I studied several open source solutions to get a better understanding for what was all involved. Many long hours later (and many hours spent beforehand as well), and I was finally able to figure it out well enough for what I needed. But it is fairly complex. Too complex to write about here, it would take a chapter of a book just to explain the concepts. And even then I'm still fuzzy on some details (I'm still working through it).

    I can now understand why people sell components for this!

    I found that most open source solutions don't really deal nicely with lists. They generally somewhat work but most have glaring bugs. That or they just don't really handle anything but the most basic cases of lists.

    Here is a list of systems I looked at to understand how they work to get a better understanding of everything. I unfortunately found the documentation lacking or hard to understand, so looking at these projects helped me more than anything else.

    The most helpful

    Moderately helpful (more complex, buggy, less relevant, etc.)

    Additional links

    Paid