2011-12-29 104 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