Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrap long words in JTextPane (Java 7)

In all versions of Java up to 6, the default behaviour of a JTextPane put inside a JScrollPane was: wrap lines at word boundaries if possible. If not, then wrap them anyway.

In JDK 7, the default behaviour seems to be: wrap lines at word boundaries if possible. If not, just expand the width of the JTextPane (never wrap long words).

It is easy to reproduce this, here is a SSCCE:


public class WrappingTest extends JFrame
{

    public static void main ( String[] args )
    {
        new WrappingTest(); 
    }

    public WrappingTest ()
    {
        setSize(200,200);
        getContentPane().setLayout(new BorderLayout());
        JTextPane jtp = new JTextPane();
        JScrollPane jsp = new JScrollPane(jtp);
        jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        getContentPane().add(jsp,BorderLayout.CENTER);
        setVisible(true);
    }

}

Just run it in JDK 6 and in JDK 7, write some small words, and write a long word, and you will see the difference.

My question is simple... the new default behaviour in JDK 7 totally messes a program of mine (they should be more careful at Oracle with changing this kind of defaults... they seem unimportant but when you're using a JTextPane to display data that usually contains very long strings of letters, they're not so unimportant - in fact I'm going to file a bug report, but I'd like to have a workaround while/if they don't resolve it). Any way to go back to the previous behaviour?

Note that I have checked the answer to the related question How is word-wrapping implemented in JTextPane, and how do I make it wrap a string without spaces? but it doesn't answer this question - it provides a way of making the JTextPane wrap without any regard at all for whitespace, but for me the desired behaviour is split lines at whitespace if possible, and elsewhere if not possible (as in previous Java versions).

like image 849
Al-Khwarizmi Avatar asked Dec 29 '11 10:12

Al-Khwarizmi


People also ask

How do you make JTextPane wrap text?

To wrap the lines of JTextArea we need to call the setLineWrap(boolean wrap) method and pass a true boolean value as the parameter. The setWrapStyleWord(boolean word) method wrap the lines at word boundaries when we set it to true .

How do you wrap text in Java?

The first wrap() method takes the String to wrap as its first argument and the wrap length as its second argument. The second wrap() method takes for arguments. The first is the String to wrap and the second is the wrap length. The third is the newline characters to use when a line is wrapped.

How do you wrap a label in Java?

As per @darren's answer, you simply need to wrap the string with <html> and </html> tags: myLabel. setText("<html>"+ myString +"</html>"); You do not need to hard-code any break tags.

What is JTextArea in Java?

A JTextArea is a multi-line area that displays plain text. It is intended to be a lightweight component that provides source compatibility with the java. awt. TextArea class where it can reasonably do so.


1 Answers

For me the fix works (tested under 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);
            }
        }

    }
}
like image 178
StanislavL Avatar answered Oct 14 '22 15:10

StanislavL