Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JEditorPane.getPreferredSize not always working in Java 9?

This question is about different behaviour of JEditorPane in Java 8 and Java 9. I’d like to know if others have experienced the same, whether it could be a bug in Java 9, and if possible have your input to how to handle it in Java 9.

Context: In our (age-old) code base we are using a subclass of JTable, and for rendering multi-line HTML in one of the columns we are using a subclass of JEditorPane. We are using JEditorPane.getPreferredSize() for determining the height of the content and using it for setting the height of the table row. It’s been working well for many years. It doesn’t work in Java 9; the rows are displayed just 10 pixels high. Seen both on Windows and Mac.

I should like to show you two code examples. If the first and shorter one suffices for you, feel free to skip the second and longer one.

MCVE:

JEditorPane pane = new JEditorPane("text/html", "");

pane.setText("<html>One line</html>");
System.out.println(pane.getPreferredSize());
pane.setText("<html>Line one<br />Line 2<br />Third line<br />Line four</html>");
System.out.println(pane.getPreferredSize());

Output in Java 8 (1.8.0_131):

java.awt.Dimension[width=48,height=15]
java.awt.Dimension[width=57,height=60]

And on Java 9 (jdk-9.0.4):

java.awt.Dimension[width=49,height=15]
java.awt.Dimension[width=58,height=0]

In Java 9 the first time I set the text, the preferred height reflects it. Every subsequent time it doesn’t.

I have searched to see if I could find any information on a bug that might account for this, did not find anything relevant.

Question: Is this intended (change of) behaviour? Is it a bug??

Longer example

public class TestJEditorPaneAsRenderer extends JFrame {

    public TestJEditorPaneAsRenderer() {
        super("Test JEditorPane");
        
        MyRenderer renderer = new MyRenderer();
        
        String html2 = "<html>one/2<br />two/2</html>";
        String html4 = "<html>one of four<br />two of four<br />"
                + "three of four<br />four of four</html>";
        JTable table = new JTable(new String[][] { { html2 }, { html4 } },
                                  new String[] { "Dummy col title" }) {
            @Override
            public TableCellRenderer getDefaultRenderer(Class<?> colType) {
                return renderer;
            }
        };
        
        add(table);
        setSize(100, 150);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        System.out.println(System.getProperty("java.version"));
        new TestJEditorPaneAsRenderer().setVisible(true);
    }

}

class MyRenderer extends JEditorPane implements TableCellRenderer {

    public MyRenderer() {
        super("text/html", "");
    }
    
    @Override
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean selected, boolean hasFocus, int row, int col) {
        setText(value.toString());
        Dimension preferredSize = getPreferredSize();
        System.out.format("Row %d preferred size %s%n",row, preferredSize);
        if (preferredSize.height > 0 && table.getRowHeight(row) != preferredSize.height) {
            table.setRowHeight(row, preferredSize.height);
        }
        return this;
    }
    
}

Result on Java 8 is as expected:

Java 8 screen shot

Output from Java 8:

1.8.0_131
Row 0 preferred size java.awt.Dimension[width=32,height=30]
Row 1 preferred size java.awt.Dimension[width=72,height=60]
Row 0 preferred size java.awt.Dimension[width=32,height=30]
Row 1 preferred size java.awt.Dimension[width=72,height=60]

On Java 9 the second row is not shown high enough so most of the lines are hidden:

Java 9 screen shot showing problem

Output from Java 9:

9.0.4
Row 0 preferred size java.awt.Dimension[width=33,height=30]
Row 1 preferred size java.awt.Dimension[width=73,height=0]
Row 0 preferred size java.awt.Dimension[width=33,height=0]
Row 1 preferred size java.awt.Dimension[width=73,height=0]

A possible fix is if I create a new renderer component each time by changing the body of getDefaultRenderer() to:

return new MyRenderer();

Now the table looks good as on Java 8. If necessary I suppose we could live with a similar fix in our production code, but it seems quite a waste. Especially if it’s only necessary until the behaviour change is reverted in a coming Java version.

like image 565
Ole V.V. Avatar asked Mar 14 '18 08:03

Ole V.V.


1 Answers

I have faced similar problem, but with JLabel. My solution was to set the size of the JLabel which seems to force the component to recalculate its preferred size.

Try this:

JEditorPane pane = new JEditorPane("text/html", "");

pane.setText("<html>One line</html>");
System.out.println(pane.getPreferredSize());
pane.setText("<html>Line one<br />Line 2<br />Third line<br />Line four</html>");

// get width from initial preferred size, height should be much larger than necessary
pane.setSize(61, 1000);

System.out.println(pane.getPreferredSize());

In this casse the output is

java.awt.Dimension[width=53,height=25]
java.awt.Dimension[width=61,height=82]

Note: my fonts are different, that is why I get different dimensions.

Edit: I changed your getTableCellRendererComponent in the longer example like this and it is working for me. I am using jdk9.0.4, 64 bit.

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean hasFocus, int row, int col) {
    setText(value.toString());

    Dimension preferredSize = getPreferredSize();
    setSize(new Dimension(preferredSize.width, 1000));
    preferredSize = getPreferredSize();

    System.out.format("Row %d preferred size %s%n", row, preferredSize);
    if (preferredSize.height > 0 && table.getRowHeight(row) != preferredSize.height) {
        table.setRowHeight(row, preferredSize.height);
    }
    return this;
}
like image 71
MatheM Avatar answered Sep 19 '22 15:09

MatheM