example codigo java swing word-wrap java-7 jtextpane

codigo - Envolver palabras largas en JTextPane(Java 7)



jtextpane example (4)

En todas las versiones de Java hasta 6, el comportamiento predeterminado de un JTextPane colocado dentro de un JScrollPane era: enrolle las líneas en los límites de palabras si es posible. Si no, entonces envuélvelos de todos modos.

En JDK 7, el comportamiento predeterminado parece ser: enrollar líneas en los límites de palabras si es posible. Si no, simplemente expanda el ancho de JTextPane (nunca envuelva palabras largas).

Es fácil reproducir esto, aquí hay un 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); } }

Simplemente ejecútelo en JDK 6 y en JDK 7, escriba algunas palabras pequeñas y escriba una palabra larga, y verá la diferencia.

Mi pregunta es simple ... el nuevo comportamiento predeterminado en JDK 7 confunde totalmente un programa mío (deberían ser más cuidadosos en Oracle al cambiar este tipo de valores predeterminados) no parecen ser importantes, pero cuando se usa un JTextPane para mostrar los datos que generalmente contienen cadenas de letras muy largas, no son tan poco importantes; de hecho, presentaré un informe de error, pero me gustaría tener una solución temporal mientras / si no lo resuelven). ¿Alguna forma de volver al comportamiento anterior?

Tenga en cuenta que he comprobado la respuesta a la pregunta relacionada ¿ Cómo se implementa el ajuste de palabras en JTextPane y cómo hago que se ajuste una cadena sin espacios? pero no responde a esta pregunta: proporciona una forma de hacer que JTextPane se ajuste sin ningún tipo de espacio en blanco, pero para mí el comportamiento deseado es líneas divididas en el espacio en blanco si es posible, y en otros lugares si no es posible (como en Java anterior versiones).


Buena captura de @ dk89, pero lamentablemente las soluciones alternativas dadas no funcionan: JDK 7 aparentemente todavía no ofrece una espera para establecer un BreakIterator personalizado en un JTextComponent; ni siquiera en un GlyphView, donde la generación del BreakIterator es privada. Y si insertamos la cadena char por char, todavía no funciona: supongo que las ejecuciones consecutivas de texto con estilo idéntico (AttributeSet) se contraen juntas.

He pasado dos días tratando de hacer un EditorKit personalizado, como se recomienda en otra parte, pero no funciona bien (con JDK 1.7.0_4 al menos) como texto.

Probé la solución dada en Cómo envolver el texto almacenado en JTextPanes, que son celdas en un JList y en una variante encontrada en http://www.experts-exchange.com/Programming/Languages/Java/Q_20393892.html

Pero descubrí que ya no se llama a breakView cuando JTextPane es más pequeño que la palabra más larga de la oración. Así que no funciona en absoluto cuando hay una sola palabra (larga). Ese es nuestro caso, ya que mostramos cadenas tipo identificador proporcionadas por el usuario, a menudo sin espacios, en espacios más bien pequeños.

Finalmente encontré una solución simple, derivada de la sugerencia en el informe de error: de hecho, inserte la cadena char por char, ¡pero alterne los estilos! Por lo tanto, tenemos tantos segmentos como caracteres, y la cadena está envuelta en los límites de caracteres. ¿Hasta la próxima "corrección de errores"?

Fragmentos de código:

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

Como se indica en el error, deberían haber proporcionado una forma fácil (algunas propiedades quizás, o algunas cosas inyectables) para volver al comportamiento anterior.



Hola, he tenido el mismo problema pero encontré una solución:

solo crea una clase extendida de JTextPane por ejemplo

MyWrapJTextPane extends JTextPane

y sobrescribe el siguiente método - funciona ;-)

public boolean getScrollableTracksViewportWidth() { return true; }


Para mi el arreglo funciona (probado bajo 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); } } } }