Search code examples
javaswingjava-8

JOptionPane: ignore line feeds in HTML


Can I make Swing's JOptionPane tolerate line feeds in HTML? For example, this displays the string hello (as I expect).

package demos.dialog.optionPane;

import javax.swing.JOptionPane;

public class JOptionPaneDemo {
    public static void main(String[] args) {
        JOptionPane.showMessageDialog(null, "<html>Hello</html>");
    }
}

while this one displays Hello</html> instead

package demos.dialog.optionPane;

import javax.swing.JOptionPane;

public class JOptionPaneDemo {
    public static void main(String[] args) {
        JOptionPane.showMessageDialog(null, "<html>\nHello</html>");
    }
}

a line feed is included, Hello is displayed

Note the HTML text comes from a DB, I cannot prevent such inputs. Besides, it's a valid HTML anyway, so there's nothing to sanitize really. Unless I'm misunderstanding the spec, all whitespace must be ignored during HTML rendering. Online renderers like this one also have no problem parsing it.

HTML with a line feed is rendered alright in an online editor

Is there a solution to this problem that doesn't involve manually replacing all line feeds to make Swing happy?

Java 8.


Solution

  • The problem is that JOptionPane does not just delegate the text rendering to another component like JLabel but has a multi-line support on its own that interferes with the other text processing.

    E.g. JOptionPane.showMessageDialog(null, "hello\nworld"); will render two lines of text, using two JLabel instances.

    When you use the message "<html>\nHello</html>", the JOptionPane will split it into two “lines”, "<html>" and "Hello</html>", and create a JLabel for each. The first will have HTML rendering enabled but produce no visible content whilst the second will have HTML rendering disabled, to the result we see.

    The solution is to enforce having a single JLabel as a message, processing the entire string as one HTML page:

    JOptionPane.showMessageDialog(null, new JLabel("<html>\nHello</html>"));