首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在JTextPane中对长词进行换行(Java7)

在JTextPane中对长词进行换行(Java7)
EN

Stack Overflow用户
提问于 2011-12-29 18:33:39
回答 4查看 5.3K关注 0票数 16

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

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

这很容易重现,这是一个SSCCE:

代码语言:javascript
复制
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显示通常包含非常长的字母字符串的数据时,它们并不是那么不重要-事实上,我将提交一份错误报告,但如果它们不能解决这个问题,我希望有一个解决办法)。有没有办法回到之前的行为?

请注意,我已经检查了相关问题How is word-wrapping implemented in JTextPane, and how do I make it wrap a string without spaces?的答案,但它并没有回答这个问题-它提供了一种使JTextPane换行而完全不考虑空格的方法,但对我来说,所需的行为是在可能的情况下在空格处分割线条,如果不可能的话在其他地方(如在以前的Java版本中)。

EN

回答 4

Stack Overflow用户

发布于 2012-11-14 17:08:14

对我来说,这个修复是有效的(在1.7.0_09下测试)

代码语言:javascript
复制
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);
            }
        }

    }
}
票数 12
EN

Stack Overflow用户

发布于 2012-06-27 22:51:21

从@dk89捕捉到的不错,但遗憾的是,给定的变通方法不起作用:JDK7显然仍然不提供在JTextComponent上设置自定义BreakIterator的等待;甚至在GlyphView上也不提供,在GlyphView上,BreakIterator的生成是私有的。如果我们逐个字符地插入字符串char,它仍然不起作用:我假设具有相同样式(AttributeSet)的连续文本串折叠在一起。

我花了两天的时间尝试做一个自定义的EditorKit,就像其他地方建议的那样,但它并不像文本那样工作得很好(至少对于JDK 1.7.0_4 )。

我尝试了在How to word wrap text stored in JTextPanes which are cells in a JList给出的解决方案和在http://www.experts-exchange.com/Programming/Languages/Java/Q_20393892.html找到的一个变体

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

我最终找到了一个简单的解决方案,源自bug报告中的建议:确实,逐个字符地插入字符串char,但要有不同的样式!因此,我们有和字符一样多的段,字符串被包装在字符的边界上。直到下一个"bug修复“?

代码片段:

代码语言:javascript
复制
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中所述,它们应该提供一种简单的方法(可能是一些属性,或者一些可注入的东西)来恢复到旧的行为。

票数 3
EN

Stack Overflow用户

发布于 2011-12-29 23:19:20

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8666727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档