【问题标题】:Wrap long words in JTextPane (Java 7)在 JTextPane (Java 7) 中包装长单词
【发布时间】:2012-01-29 19:18:36
【问题描述】:

在Java 6 之前的所有版本中,放在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 显示通常包含非常长的字母字符串的数据,它们并不是那么不重要 - 事实上我要提交一个错误报告,但我想有一个解决方法,而/如果他们不解决它)。有什么办法可以回到以前的行为?

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

【问题讨论】:

标签: java swing word-wrap java-7 jtextpane


【解决方案1】:

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

    }
}

【讨论】:

  • 事实上,我们只需要让 LabelView 的 getMinimumSpan() 为 X_AXIS 返回 0。 ViewFactory 是一种替换默认 LabelView 的方法
  • aaach 我可以看到并得到它,谢谢,也非常适合 jtp.setComponentOrientation(RTL); 工作
  • 我们应该如何解决 jtp.setEditorKit(new WrapEditorKit()); 行中的转换问题?我在该行中得到一个 javax.swing.text.DefaultStyledDocument 无法转换为 javax.swing.text.html.HTMLDocument。
  • 您使用另一个编辑器工具包。猜猜HTMLEditorKit。对套件做同样的事情。
【解决方案2】:

来自@dk89 的好消息,但很遗憾,给定的解决方法不起作用:JDK 7 显然仍然不提供在 JTextComponent 上设置自定义 BreakIterator 的等待;甚至在 BreakIterator 的生成是私有的 GlyphView 上也不行。如果我们逐个字符插入字符串,它仍然不起作用:我想具有相同样式(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 的变体

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

我终于找到了一个简单的解决方案,源自错误报告中的建议:确实,逐个字符插入字符串,但样式不同!因此,我们有与字符一样多的段,并且字符串被包装在字符边界处。直到下一个“错误修复”?

代码sn-ps:

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

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

【讨论】:

    【解决方案3】:

    您好,我遇到了同样的问题,但找到了解决方法:

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

            MyWrapJTextPane extends JTextPane
    

    并覆盖以下方法 - 它有效;-)

            public boolean getScrollableTracksViewportWidth() {
                return true;
            }
    

    【讨论】:

    • 对不起:没有不行!这只解决了长行(包含空格)的问题——它们现在被正确包装了——但长词仍然没有被包装:-(
    【解决方案4】:

    【讨论】:

    • 谢谢,它非常相似......但不幸的是,它似乎不是同一个错误(它与属性集有关,并且很久以前就已修复):/
    • 嗯,我认为这是相关的,尽管 1.6 中的行为没有改变。查看评论:“应该注意,请求的默认拆分行为(在 BreakIterator 未找到有效断点时在任意位置破坏 GlyphView)是非常错误的,不应在任何 JDK 版本中恢复,无论是未来还是过去。”看来我们现在需要做更多的工作......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多