2011-12-29 56 views
16

在所有版本的Java到6中,JTextPane放置在JScrollPane中的默认行为是:如果可能,在单词边界处包装行。如果不是,那就把它们包起来。在JTextPane中包装长单词(Java 7)

在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版本)。

+0

是否使用['的invokeLater()'](http://download.oracle.com/javase/tutorial/uiswing/concurrency/ initial.html)的帮助? – 2011-12-29 14:36:52

+0

不......同样的效果。 – 2011-12-29 19:36:41

+0

我有完全相同的问题。相关:https://forums.oracle.com/forums/thread.jspa?threadID=2374090(没有答案...)那里的海报已经创建了一个错误报告,但它被关闭为“没有错误”,没有解释的话...... – PhiLho 2012-05-31 11:21:14

回答

1
+0

谢谢,这是非常相似......但不幸的是它似乎不相同的bug(它与属性集做的,是很久以前固定):/ – 2011-12-29 16:42:46

+0

嗯,我觉得它是相关的,尽管1.6中的行为没有改变。看看评论:“应当指出的是,所请求的默认分裂行为(在任意地方打破GlyphView当没有有效的断点通过的BreakIterator发现)是可怕的错误,不应该在任何JDK版本中恢复,无论是将来或过去的。”看起来我们现在需要做更多的工作... – PhiLho 2012-05-31 11:24:56

1

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

只是创建一个扩展类的JTextPane例如中

 MyWrapJTextPane extends JTextPane 

并覆盖下面的方法 - 它工作;-)

 public boolean getScrollableTracksViewportWidth() { 
      return true; 
     } 
+0

抱歉:不行不行!这只能解决问题排长(含白空格) - 他们现在正确地包裹 - 但长期的话还是没有得到包裹:-( – Thomwiesel 2012-01-02 19:10:25

2

良好的渔获来自@ dk89,但可惜给出解决方法不起作用:JDK 7显然还是不提供等待在JTextComponent上设置一个自定义的BreakIterator;即使在一个GlyphView中,BreakIterator的生成是私有的。如果我们通过char插入字符串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比在句子中最长的字小。所以当只有一个(长)字时它根本不起作用。这就是我们的情况,因为我们在相当小的空间中显示用户提供的,类似标识符的字符串,通常没有空格。

我终于找到了一个简单的解决方案,从错误报告中的建议中派生出来:实际上,通过char插入字符串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); 
    } 

正如错误陈述,他们应该提供一个简单的方法(某些属性也许,或一些可注射的东西),恢复到原来的行为。

11

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

    } 
} 
+0

+1 Java7 :-),有趣的ViewFactory – mKorbel 2012-11-14 09:27:48

+1

其实我们所需要的是让LabelView的getMinimumSpan()为X_AXIS返回0。 ViewFactory是一种替代默认LabelView – StanislavL 2012-11-14 09:36:48

+0

的方法,我可以看到并得到它,谢谢,相当正确地为'jtp.setComponentOrientation(RTL)'工作;' – mKorbel 2012-11-14 09:42:35