This discussion is archived
6 Replies Latest reply: Dec 20, 2012 4:18 AM by 974868 RSS

Word wraping behaviour in JTextPane since Java 7

908455 Newbie
Currently Being Moderated
Hi,
I have the following problem. I've always used a JTextPane in a small editor application. Until Java version 1.6.x the wrapping of long lines worked without any problems automatically (long lines have been wrapped if possible between words, if not possible (e.g. with very long words) inside the word at the right border of the JTextPane).

Since Java 7 the wrap behaviour has changed. If you now have a long line a horizontal scrollbar appears, no wrapping is done anymore. It seems the EditorKit has somehow changed - but I found no documentation.

First step I've tried:
overridden JTextPane and added the following method

     @Override
     public boolean getScrollableTracksViewportWidth() {
          return true;
     }

But this helps only 50% :-( long lines are now wrapped correctly if you have space between the words, but if you have a really long word a strange behaviour occurs: sometimes wrapping is done but mostly not. I have no idea.

I've already found a bug-report at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7125737 but the report was closed as "not a bug".

I'm using the default EditorKit - has anyone what exactly has to be changed/added so the wrap behaviour of long lines is again the same in Java 7 as in Java 6 and earlier?

I think you have to somehow override the EditorKit but unfortunately I don't how to do this (found the following examples but don't know if it helps and didn't get to adapt it http://java-sl.com/wrap.html )

Thank you very much for your help
  • 1. Re: Word wraping behaviour in JTextPane since Java 7
    StanislavL Pro
    Currently Being Moderated
    The fix works for me. Tested under jdk 1.7.0_09
    import javax.swing.*;
    import javax.swing.text.*;
    import java.awt.*;
    
    public class WrapTestApp extends JFrame {
    
        public static void main ( String[] args ) {
            new WrapTestApp();
        }
    
        public WrapTestApp () {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(200,200);
            getContentPane().setLayout(new BorderLayout());
            JTextPane jtp = new JTextPane();
            jtp.setEditorKit(new WrapEditorKit());
            JScrollPane jsp = new JScrollPane(jtp);
            jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
            getContentPane().add(jsp, BorderLayout.CENTER);
            jtp.setText("ExampleOfTheWrapLongWordWithoutSpaces");
            setVisible(true);
        }
    
        class WrapEditorKit extends StyledEditorKit {
            ViewFactory defaultFactory=new WrapColumnFactory();
            public ViewFactory getViewFactory() {
                return defaultFactory;
            }
    
        }
    
        class WrapColumnFactory implements ViewFactory {
            public View create(Element elem) {
                String kind = elem.getName();
                if (kind != null) {
                    if (kind.equals(AbstractDocument.ContentElementName)) {
                        return new WrapLabelView(elem);
                    } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
                        return new ParagraphView(elem);
                    } else if (kind.equals(AbstractDocument.SectionElementName)) {
                        return new BoxView(elem, View.Y_AXIS);
                    } else if (kind.equals(StyleConstants.ComponentElementName)) {
                        return new ComponentView(elem);
                    } else if (kind.equals(StyleConstants.IconElementName)) {
                        return new IconView(elem);
                    }
                }
    
                // default to text display
                return new LabelView(elem);
            }
        }
    
        class WrapLabelView extends LabelView {
            public WrapLabelView(Element elem) {
                super(elem);
            }
    
            public float getMinimumSpan(int axis) {
                switch (axis) {
                    case View.X_AXIS:
                        return 0;
                    case View.Y_AXIS:
                        return super.getMinimumSpan(axis);
                    default:
                        throw new IllegalArgumentException("Invalid axis: " + axis);
                }
            }
    
        }
    }
  • 2. Re: Word wraping behaviour in JTextPane since Java 7
    974868 Newbie
    Currently Being Moderated
    Hi,

    I've the same problem, not with text but with components like JLabel. In Java 6 there was break done between two labels if needed, in Java 7 no break but the scrollbar.

    What exactly has been changed in Java 7, does anyone know?

    Thanks and regards
  • 3. Re: Word wraping behaviour in JTextPane since Java 7
    974868 Newbie
    Currently Being Moderated
    simple answer, a WrapComponentView:
        class WrapComponentView extends ComponentView {
            public WrapComponentView(Element elem) {
                super(elem);
            }
    
            @Override
            public float getMinimumSpan(int axis) {
                switch (axis) {
                case View.X_AXIS:
                    return 0;
                case View.Y_AXIS:
                    return super.getMinimumSpan(axis);
                default:
                    throw new IllegalArgumentException("Invalid axis: " + axis);
                }
            }
        }
    But it's still ugly that the behaviour in Java 7 changed and I'm really interested in what changes were made in Java 7 by oracle?
  • 4. Re: Word wraping behaviour in JTextPane since Java 7
    974868 Newbie
    Currently Being Moderated
    Hi Stanislav,

    thanks for this nice workaround!
    Could you please explain in a few words why this is working. How does the minimumSpan = 0 on the x-axis effect the wrapping?

    Thank you
  • 5. Re: Word wraping behaviour in JTextPane since Java 7
    StanislavL Pro
    Currently Being Moderated
    They changed algorithm of minimum size calculation. The logic is following when a row is bigger than available width the row must be broken. The first part (row) should be less than available width. The rest again is measured and can be broken once more if it's bigger than available width.

    Now the tric. Size of content is defined by minimumSpan (can't be less than minimal possible). So when it's in a scroll scroll measures width and asks for minimal span. Then width of JScrollPane's content =width of vieport (or if min width is bigger =min width).

    Thus when we say min=0 we always use the viewport width.

    Understand?
  • 6. Re: Word wraping behaviour in JTextPane since Java 7
    974868 Newbie
    Currently Being Moderated
    Ok, I got it.

    Thanks again

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points