2012-06-12 17 views
14

Tengo dos editores diferentes que usan JTextPane con errores extraños en Java 7 que no ocurrieron con las versiones anteriores de JVM. Sucede con largas líneas que contienen texto con estilo o componentes.Encaje de texto extraño con texto con estilo en JTextPane con Java 7

Aquí hay un ejemplo que demuestra este error. En este ejemplo, el estilo predeterminado se aplica a todo el texto cada vez que se inserta un carácter. Lo probé con el JDK 1.7.0_04.

import java.awt.BorderLayout; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.text.*; 

public class BugWrapJava7 extends JFrame { 

    JTextPane jtp; 
    StyledDocument doc; 

    public BugWrapJava7() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLayout(new BorderLayout()); 
     jtp = new JTextPane(); 
     add(jtp, BorderLayout.CENTER); 
     jtp.setText("\ntype some text in the above empty line and check the wrapping behavior"); 
     doc = jtp.getStyledDocument(); 
     doc.addDocumentListener(new DocumentListener() { 
      public void insertUpdate(DocumentEvent e) { 
       insert(); 
      } 
      public void removeUpdate(DocumentEvent e) { 
      } 
      public void changedUpdate(DocumentEvent e) { 
      } 
     }); 
     setSize(200, 200); 
     setVisible(true); 
    } 
    public void insert() { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       Style defaultStyle = jtp.getStyle(StyleContext.DEFAULT_STYLE); 
       doc.setCharacterAttributes(0, doc.getLength(), defaultStyle, false); 
      } 
     }); 
    } 
    public static void main(String[] args) { 
     new BugWrapJava7(); 
    } 
} 

Mi pregunta es: ¿hay algo mal en mi código, o es de hecho un nuevo error introducido en Java 7? Y si se trata de un nuevo error de JVM, ¿hay alguna solución?

Podría estar relacionado con question 8666727, pero el problema aquí radica en la envoltura incorrecta en lugar de la apariencia de una barra de desplazamiento.

+0

tiene usted razón, he visto que la diferencia y pueden comparar 1, ninguna idea acerca de los cambios en Java7 (dejando mi actualización en Java 1.7.0_15 y más) – mKorbel

+0

Probablemente no va a ayudar, pero llaman 'paquete() 'inmediatamente antes de' setSize (200, 200); '(no tengo Java 7 disponible para probarlo). –

+0

@Andrew Thompson Agregué todos los buenos Swul rulles, sin ningún cambio, por favor vea en mi publicación aquí – mKorbel

Respuesta

16

para los lectores futuros, bug is still present in JDK 1.7.0_04.,

comparando Java7 y con java6 estable,

enter image description here < ------ Java7 V.S. Java6 --->enter image description here

enter image description here < ------ Java7 v.s. Java6 --->enter image description here

enter image description here < ------ Java7 v.s. Java6 --->enter image description here

enter image description here < ------ Java7 v.s. Java6 --->enter image description here

de código

import java.awt.Dimension; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.text.*; 

public class BugWrapJava7 { 

    private JFrame frame = new JFrame(); 
    private JTextPane jtp; 
    private StyledDocument doc; 

    public BugWrapJava7() { 
     jtp = new JTextPane(); 
     jtp.setText("\ntype some text in the above empty line and check the wrapping behavior"); 
     doc = jtp.getStyledDocument(); 
     doc.addDocumentListener(new DocumentListener() { 

      public void insertUpdate(DocumentEvent e) { 
       insert(); 
      } 

      public void removeUpdate(DocumentEvent e) { 
       insert(); 
      } 

      public void changedUpdate(DocumentEvent e) { 
       insert(); 
      } 

      public void insert() { 
       SwingUtilities.invokeLater(new Runnable() { 

        public void run() { 
         Style defaultStyle = jtp.getStyle(StyleContext.DEFAULT_STYLE); 
         doc.setCharacterAttributes(0, doc.getLength(), defaultStyle, false); 
        } 
       }); 
      } 
     }); 
     JScrollPane scroll = new JScrollPane(jtp); 
     scroll.setPreferredSize(new Dimension(200, 200)); 
     frame.add(scroll); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      public void run() { 
       BugWrapJava7 bugWrapJava7 = new BugWrapJava7(); 
      } 
     }); 
    } 
} 
+0

'<------ Java7 v.s. Java6 ---> 'Eso está haciendo un esfuerzo adicional. +1 –

+0

@Andrew Thompson jejeje este es el mismo modo, porque no soy bueno en Html, y no puedo crear un espacio entre dos imágenes – mKorbel

+0

Espero que sea mejor, por favor vea mi actualización ... :-) – mKorbel

7

investigado este. El motivo es el almacenamiento en memoria caché de breakSpots. Parece que LabelView los almacena y no vuelve a calcular las compensaciones en la edición de texto anterior. Si los reinicio manualmente, el error no ocurre.

Una solución (muy sucio debido a campos privados breakSpots) está siguiendo

import java.awt.Dimension; 
import java.lang.reflect.Field; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.text.*; 

public class BugWrapJava7 { 

    private JFrame frame = new JFrame(); 
    private JTextPane jtp; 
    private StyledDocument doc; 

    public BugWrapJava7() { 
     jtp = new JTextPane(); 
     jtp.setEditorKit(new MyStyledEditorKit()); 
     jtp.setText("\ntype some text in the above empty line and check the wrapping behavior"); 
     doc = jtp.getStyledDocument(); 
     doc.addDocumentListener(new DocumentListener() { 

      public void insertUpdate(DocumentEvent e) { 
       insert(); 
      } 

      public void removeUpdate(DocumentEvent e) { 
       insert(); 
      } 

      public void changedUpdate(DocumentEvent e) { 
       insert(); 
      } 

      public void insert() { 
       SwingUtilities.invokeLater(new Runnable() { 

        public void run() { 
         Style defaultStyle = jtp.getStyle(StyleContext.DEFAULT_STYLE); 
         doc.setCharacterAttributes(0, doc.getLength(), defaultStyle, false); 
        } 
       }); 
      } 
     }); 
     JScrollPane scroll = new JScrollPane(jtp); 
     scroll.setPreferredSize(new Dimension(200, 200)); 
     frame.add(scroll); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      public void run() { 
       BugWrapJava7 bugWrapJava7 = new BugWrapJava7(); 
      } 
     }); 
    } 
} 

class MyStyledEditorKit extends StyledEditorKit { 
    private MyFactory factory; 

    public ViewFactory getViewFactory() { 
     if (factory == null) { 
      factory = new MyFactory(); 
     } 
     return factory; 
    } 
} 

class MyFactory implements ViewFactory { 
    public View create(Element elem) { 
     String kind = elem.getName(); 
     if (kind != null) { 
      if (kind.equals(AbstractDocument.ContentElementName)) { 
       return new MyLabelView(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 MyLabelView extends LabelView { 
    public MyLabelView(Element elem) { 
     super(elem); 
    } 
    public View breakView(int axis, int p0, float pos, float len) { 
     if (axis == View.X_AXIS) { 
      resetBreakSpots(); 
     } 
     return super.breakView(axis, p0, pos, len); 
    } 

    private void resetBreakSpots() { 
     try { 
      // HACK the breakSpots private fields 
      Field f=GlyphView.class.getDeclaredField("breakSpots"); 
      f.setAccessible(true); 
      f.set(this, null); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 

Menos truco sin la reflexión. Basado en el reinicio habitual de breakSpots en el cambio de modelo.

class MyLabelView extends LabelView { 

    boolean isResetBreakSpots=false; 

    public MyLabelView(Element elem) { 
     super(elem); 
    } 
    public View breakView(int axis, int p0, float pos, float len) { 
     if (axis == View.X_AXIS) { 
      resetBreakSpots(); 
     } 
     return super.breakView(axis, p0, pos, len); 
    } 

    private void resetBreakSpots() { 
     isResetBreakSpots=true; 
     removeUpdate(null, null, null); 
     isResetBreakSpots=false; 

//  try { 
//   Field f=GlyphView.class.getDeclaredField("breakSpots"); 
//   f.setAccessible(true); 
//   f.set(this, null); 
//  } catch (Exception e) { 
//   e.printStackTrace(); 
//  } 
    } 

    public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) { 
     super.removeUpdate(e, a, f); 
    } 

    public void preferenceChanged(View child, boolean width, boolean height) { 
     if (!isResetBreakSpots) { 
      super.preferenceChanged(child, width, height); 
     } 
    } 
} 

ACTUALIZACIÓN: Esta también soluciona TextSamplerDemo. Restablecí todos los espacios para todas las vistas de etiquetas.

class MyStyledEditorKit extends StyledEditorKit { 
    private MyFactory factory; 

    public ViewFactory getViewFactory() { 
     if (factory == null) { 
      factory = new MyFactory(); 
     } 
     return factory; 
    } 
} 

class MyFactory implements ViewFactory { 
    public View create(Element elem) { 
     String kind = elem.getName(); 
     if (kind != null) { 
      if (kind.equals(AbstractDocument.ContentElementName)) { 
       return new MyLabelView(elem); 
      } else if (kind.equals(AbstractDocument.ParagraphElementName)) { 
       return new MyParagraphView(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 MyParagraphView extends ParagraphView { 

    public MyParagraphView(Element elem) { 
     super(elem); 
    } 
public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) { 
    super.removeUpdate(e, a, f); 
    resetBreakSpots(); 
} 
public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) { 
    super.insertUpdate(e, a, f); 
    resetBreakSpots(); 
} 

private void resetBreakSpots() { 
    for (int i=0; i<layoutPool.getViewCount(); i++) { 
     View v=layoutPool.getView(i); 
     if (v instanceof MyLabelView) { 
      ((MyLabelView)v).resetBreakSpots(); 
     } 
    } 
} 

} 

class MyLabelView extends LabelView { 

    boolean isResetBreakSpots=false; 

    public MyLabelView(Element elem) { 
     super(elem); 
    } 
    public View breakView(int axis, int p0, float pos, float len) { 
     if (axis == View.X_AXIS) { 
      resetBreakSpots(); 
     } 
     return super.breakView(axis, p0, pos, len); 
    } 

    public void resetBreakSpots() { 
     isResetBreakSpots=true; 
     removeUpdate(null, null, null); 
     isResetBreakSpots=false; 
    } 

    public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) { 
     super.removeUpdate(e, a, f); 
    } 

    public void preferenceChanged(View child, boolean width, boolean height) { 
     if (!isResetBreakSpots) { 
      super.preferenceChanged(child, width, height); 
     } 
    } 
} 
+0

[similair hack/workaround by (@StanislavL) para Java7 y JTextArea] (http://stackoverflow.com/a/14218102/714968) – mKorbel

+0

Gracias por esta solución. Funciona bien para la prueba. También mejora el comportamiento en un editor usando JComponent y estilos en el panel de texto, aunque todavía ocurren cosas extrañas (como los saltos de línea que suceden a veces sin motivo). Lamentablemente, esta solución no funciona en absoluto con los applets de Java. – Damien

+0

@Damien, por favor proporcione SSCCE para los problemas restantes y trataré de averiguar cuál es el problema. – StanislavL