在JTextPane中包装长单词(Java 7)

在JTextPane中包装长单词(Java 7),java,swing,word-wrap,java-7,jtextpane,Java,Swing,Word Wrap,Java 7,Jtextpane,在6之前的所有Java版本中,放在JScrollPane中的JTextPane的默认行为是:如果可能,在单词边界处换行。如果没有,那么无论如何都要把它们包起来 在JDK 7中,默认行为似乎是:如果可能,在单词边界处换行。如果没有,只需扩展JTextPane的宽度(不要包装长单词) 这很容易复制,这里是一个SSCCE: public class WrappingTest extends JFrame { public static void main ( String[] args )

在6之前的所有Java版本中,放在JScrollPane中的JTextPane的默认行为是:如果可能,在单词边界处换行。如果没有,那么无论如何都要把它们包起来

在JDK 7中,默认行为似乎是:如果可能,在单词边界处换行。如果没有,只需扩展JTextPane的宽度(不要包装长单词)

这很容易复制,这里是一个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);
    }

}
只需在JDK6和JDK7中运行它,写一些小词,然后写一个长词,您就会看到区别

我的问题很简单。。。JDK 7中新的默认行为完全扰乱了我的程序(在Oracle更改此类默认值时,他们应该更加小心……它们似乎不重要,但当您使用JTextPane显示通常包含很长字符串的数据时,它们并不是那么不重要——事实上,我将提交一份错误报告,但如果他们不解决它,我希望有一个解决方法).有没有办法回到以前的行为


请注意,我已经检查了相关问题的答案,但它没有回答这个问题-它提供了一种使JTextPane包装的方法,完全不考虑空格,但对我来说,所需的行为是在空格处拆分行(如果可能),在其他地方拆分行(如以前的Java版本).

看看这个bug:


嗨,我也遇到了同样的问题,但找到了解决办法:

只需创建JTextPane的扩展类,例如

        MyWrapJTextPane extends JTextPane
并覆盖以下方法-有效;-)


来自@dk89的好消息,但遗憾的是,给定的解决方法不起作用:JDK 7显然仍然没有等待在JTextComponent上设置自定义BreakIterator;即使在GlyphView上也不行,因为BreakIterator的生成是私有的。如果我们一个字符一个字符地插入字符串,它仍然不起作用:我假设具有相同样式的连续文本(AttributeSet)被折叠在一起

我花了两天的时间尝试编写一个定制的EditorKit,正如其他地方所建议的那样,但它不能很好地作为文本使用(至少使用JDK1.7.0_4)

我尝试了在中给出的解决方案,并在中找到了一个变体

但是我发现当JTextPane小于句子中最长的单词时,不再调用breakView。因此,当只有一个(长)单词时,它根本不起作用。这就是我们的情况,当我们在很小的空间中显示用户提供的、类似标识符的字符串时,通常没有空格

我终于找到了一个简单的解决方案,这个解决方案来源于bug报告中的建议:确实,逐字符插入字符串,但要使用其他样式!因此,我们有和字符一样多的段,字符串被包装在字符边界上。直到下一个“bug修复”

代码片段:

private JTextPane tp;
private SimpleAttributeSet sas = new SimpleAttributeSet();

tp= new JTextPane();
sas.addAttribute( "A", "C" ); // Arbitrary attribute names and value, not used actually

    // Set the global attributes (italics, etc.)
    tp.setParagraphAttributes(styleParagraphAttributes, true);

    Document doc = tp.getDocument();
    try
    {
        doc.remove(0, doc.getLength()); // Clear
        for (int i = 0; i < textToDisplay.length(); i++)
        {
            doc.insertString(doc.getLength(), textToDisplay.substring(i, i+1),
                    // Change attribute every other char
                    i % 2 == 0 ? null : sas);
        }
    }
    catch (BadLocationException ble)
    {
        log.warn("Cannot happen...", ble);
    }
私有jtextp;
私有SimpleAttributeSet sas=新SimpleAttributeSet();
tp=新的JTextPane();
sas.addAttribute(“A”、“C”);//任意属性名称和值,实际未使用
//设置全局属性(斜体等)
tp.setParagraphAttributes(styleParagraphAttributes,true);
Document doc=tp.getDocument();
尝试
{
doc.remove(0,doc.getLength());//清除
对于(int i=0;i
正如bug中所述,他们应该提供一种简单的方法(可能是一些属性,或者一些可注入的东西)来恢复旧的行为。

对我来说,修复程序是有效的(在1.7.0\u 09下测试)


使用有帮助吗?我也有同样的问题。相关:(没有答案…)那里的海报已经创建了一个bug报告,但它被关闭为“不是bug”,没有任何解释…谢谢,它非常相似。。。但不幸的是,这似乎不是同一个bug(它与属性集有关,很久以前就被修复了):/我认为这是相关的,尽管1.6中的行为没有改变。请看评论:“应该注意,请求的默认拆分行为(当BreakIterator找不到有效断点时,在任意位置中断GlyphView)是非常错误的,不应该在任何JDK版本中恢复,无论是将来还是过去。”看起来我们现在需要做更多的工作……抱歉:不可以!这只解决了长行(包含空格)的问题——它们现在被正确地包装了——但是长词仍然没有被包装:-(实际上我们需要的是让getMinimumSpan()对于X_轴,LabelView返回0。ViewFactory是一种替换默认LabelViewAach的方法,我可以看到并获得它,谢谢,非常正确地用于
jtp.setComponentOrientation(RTL);
Too我们如何解决jtp.setEditorKit(新的WrapEditorKit())行中的强制转换问题;?我得到一个javax.swing.text.DefaultStyledDocument不能转换为该行中的javax.swing.text.html.HTMLDocument。您使用另一个编辑器工具包。猜测HTMLEditorKit。对该工具包执行相同的操作。
private JTextPane tp;
private SimpleAttributeSet sas = new SimpleAttributeSet();

tp= new JTextPane();
sas.addAttribute( "A", "C" ); // Arbitrary attribute names and value, not used actually

    // Set the global attributes (italics, etc.)
    tp.setParagraphAttributes(styleParagraphAttributes, true);

    Document doc = tp.getDocument();
    try
    {
        doc.remove(0, doc.getLength()); // Clear
        for (int i = 0; i < textToDisplay.length(); i++)
        {
            doc.insertString(doc.getLength(), textToDisplay.substring(i, i+1),
                    // Change attribute every other char
                    i % 2 == 0 ? null : sas);
        }
    }
    catch (BadLocationException ble)
    {
        log.warn("Cannot happen...", ble);
    }
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);
            }
        }

    }
}