2011-12-29 2 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) help? –

+0

No ... такой же эффект. –

+0

У меня точно такая же проблема. Связано: https://forums.oracle.com/forums/thread.jspa?threadID=2374090 (нет ответов ...) Плакат там уже создал отчет об ошибке, но он был закрыт как «не ошибка», без слово объяснения ... – PhiLho

ответ

1

Взгляните на эту ошибку:

http://bugs.sun.com/view_bug.do?bug_id=6539700

+0

Спасибо, это очень похоже ... но, к сожалению, это не похоже на ту же ошибку (она связана с наборами атрибутов и была исправлена ​​давно):/ –

+0

Ну, я думаю, это связано, хотя поведение в 1.6 не изменилось. Посмотрите на комментарий: «Следует отметить, что запрошенное поведение расщепления по умолчанию (нарушение GlyphView в произвольном месте, когда нет допустимой точки останова, найденной BreakIterator) ужасно ошибочно и не должно быть восстановлено ни в одной версии JDK, ни в будущем, ни в прошлом». Похоже, нам нужно сделать больше работы сейчас ... – PhiLho

1

Привет У меня была такая же проблема, но нашел работу вокруг:

просто создать расширенный класс JTextPane например,

 MyWrapJTextPane extends JTextPane 

и перезаписать следующий метод - он работает ;-)

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

К сожалению: нет! это решает только проблему с длинными строками (содержащими пробелы) - они завернуты теперь правильно - но длинные слова до сих пор не обернуты :-( – Thomwiesel

2

Хороший улов от @ dk89, но увы данных обходных не работает: JDK 7, по-видимому еще не предлагает дождитесь установки пользовательского BreakIterator на JTextComponent; даже не на 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 меньше, чем самое длинное слово в предложении. Так что это не работает вообще, когда есть только одно (длинное) слово. Это наш случай, поскольку мы показываем предоставленные пользователем строки с идентификатором, часто без пробелов, в довольно небольших пространствах.

Наконец-то я нашел простое решение, полученное из предложения в отчете об ошибке: действительно, вставьте строковый символ 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

+1

На самом деле все, что нам нужно заключается в том, чтобы getMinimumSpan() LabelView возвращал 0 для X_AXIS. ViewFactory - это способ заменить стандартный LabelView – StanislavL

+0

aaach, я могу видеть и получать его, спасибо, совершенно правильно, работает для 'jtp.setComponentOrientation (RTL);' слишком – mKorbel