在JTextPane中包装长字(Java 7)

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (11)

在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);
    }

}

只需在JDK 6和JDK 7中运行它,写出一些小的单词,然后写出一个长单词,就会看到差异。

我的问题很简单...... JDK 7中的新默认行为完全混淆了我的一个程序(他们应该在Oracle中更加小心地改变这种默认设置......它们似乎并不重要,但是当您使用JTextPane显示通常包含非常长的字符串的数据,它们并不那么重要 - 事实上,我将提交一个错误报告,但是如果他们没有解决问题,我想在他/她有一个解决方法)。任何方式回到以前的行为?

提问于
用户回答回答于

来自@ dk89的好消息,但是可惜的是,给出的解决方法无效:JDK 7显然仍然没有提供等待在JTextComponent上设置自定义的BreakIterator; 即使在一个GlyphView中,BreakIterator的生成是私有的。如果我们通过char插入字符串char,它仍然不起作用:我想连续运行具有相同样式(AttributeSet)的文本会一起折叠。

我花了两天的时间尝试做一个自定义的EditorKit,正如其他地方所建议的那样,但它不能很好地工作(至少使用JDK 1.7.0_4)作为文本。

我尝试了如何将文本保存在JTextPanes中的文本中,该文本是JList中的单元格,以及http://www.experts-exchange.com/Programming/Languages/Java/Q_20393892.html中的变体

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

我终于找到了一个简单的解决方案,从错误报告中的建议中得出:事实上,通过字符插入字符串char,但替代的样式!因此,我们拥有与字符一样多的段,并且字符串被包装在字符边界处。直到下一个“错误修复”?

代码片段:

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);
    }

正如bug中所述,他们应该提供一种简单的方法(某些属性或某些可注入的东西)来恢复旧的行为。

用户回答回答于

对我来说修复工作(在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);
            }
        }

    }
}

扫码关注云+社区