2011-03-23 6 views
8

J'essaie pendant plus de 2 jours pour mettre en œuvre une exigence spécifique pour une fenêtre de l'éditeur de texte ... malheureusement sans succès jusqu'à présent :(Mettez en surbrillance la ligne actuelle JTextPane

Le but est d'obtenir une fenêtre d'éditeur de texte Avec la ligne courante, je veux dire la ligne où le curseur/caret est positionné

J'ai déjà trouvé deux approches différentes mais malheureusement je ne suis pas capable de les adopter. ils fonctionnent comme prévu

La première approche consiste à remplacer le DefaultHighlighter (http://snippets.dzone.com/posts/show/6688). Dans la seconde approche, le HighlighterPainter sera remplacé à la place (http://www.jroller.com/santhosh/date/20050622). À l'heure actuelle, j'essaie d'adopter la première approche dans mon projet, mais comme je l'ai dit, cela ne fonctionne pas comme souhaité.

À la fin de ce post, je poste un petit exemple d'application qui illustre le problème. Si je lance le programme, le signe d'insertion est placé au début de la première ligne. Cependant, la ligne n'est pas mise en évidence.

  • Maintenant, je tape quelques caractères. Ces caractères seront mis en surbrillance mais seulement ces caractères ne sont pas la ligne complète
  • J'appuie sur enter pour passer à la ligne suivante. La première ligne n'est plus mise en évidence ce qui est correct. La deuxième ligne n'est pas mise en évidence, ce qui n'est pas correct. Encore une fois, quand je tape quelques caractères, ceux-ci seront mis en évidence mais pas la rangée complète.
  • Lorsque je ramène le curseur sur la première ligne, soit par une flèche vers le haut soit par un clic de souris, la première ligne complète sera mise en surbrillance, et pas seulement les caractères existants. C'est le comportement que je veux depuis le début. J'espère que n'importe qui peut me dire ce que je fais mal ici ... ou expliquer pourquoi il n'est pas possible de résoudre ce problème du tout. Toutes les solutions alternatives comment je pourrais réaliser la mise en évidence de la ligne sont également très appréciées!

    Merci beaucoup à l'avance Vive Preachie

    import java.awt.Color; 
    import java.awt.Dimension; 
    import java.awt.Graphics; 
    import java.awt.Insets; 
    import java.awt.Rectangle; 
    
    import javax.swing.JFrame; 
    import javax.swing.JTextPane; 
    import javax.swing.event.CaretEvent; 
    import javax.swing.event.CaretListener; 
    import javax.swing.text.DefaultHighlighter; 
    import javax.swing.text.Highlighter; 
    import javax.swing.text.JTextComponent; 
    
    public class HighlightProblem extends JFrame { 
        private static final long serialVersionUID = 1L; 
        private final JTextPane textPane; 
        private final Highlighter.HighlightPainter cyanPainter; 
    
        public HighlightProblem() { 
         cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN); 
    
         textPane = new JTextPane(); 
         textPane.setPreferredSize(new Dimension(500, 300)); 
         textPane.setHighlighter(new LineHighlighter()); 
         textPane.addCaretListener(new CaretListener() { 
          @Override 
          public void caretUpdate(CaretEvent e) { 
           setHighlight(e); 
          } 
         }); 
         getContentPane().add(textPane); 
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
         pack(); 
         setVisible(true); 
        } 
    
        public static void main(String[] args) { 
         new HighlightProblem(); 
        } 
    
        public void setHighlight(CaretEvent e) { 
         textPane.getHighlighter().removeAllHighlights(); 
         int currentLine = getLineFromOffset(textPane, e.getDot()); 
         int startPos = getLineStartOffsetForLine(textPane, currentLine); 
         int endOffset = getLineEndOffsetForLine(textPane, currentLine); 
    
         try { 
          textPane.getHighlighter().addHighlight(startPos, endOffset, cyanPainter);   
         } catch (Exception ex) { 
          ex.printStackTrace(); 
         } 
         textPane.repaint(); 
        } 
    
        public int getLineFromOffset(JTextComponent component, int offset) { 
         return component.getDocument().getDefaultRootElement().getElementIndex(offset); 
        } 
    
        public int getLineStartOffsetForLine(JTextComponent component, int line) { 
         return component.getDocument().getDefaultRootElement().getElement(line).getStartOffset(); 
        } 
    
        public int getLineEndOffsetForLine(JTextComponent component, int line) { 
         return component.getDocument().getDefaultRootElement().getElement(line).getEndOffset(); 
        } 
    
        public class LineHighlighter extends DefaultHighlighter { 
         private JTextComponent component; 
    
         @Override 
         public final void install(final JTextComponent c) { 
          super.install(c); 
          this.component = c; 
         } 
    
         @Override 
         public final void deinstall(final JTextComponent c) { 
          super.deinstall(c); 
          this.component = null; 
         } 
    
         @Override 
         public final void paint(final Graphics g) { 
          final Highlighter.Highlight[] highlights = getHighlights(); 
          final int len = highlights.length; 
          for (int i = 0; i < len; i++) { 
           Highlighter.Highlight info = highlights[i]; 
           if (info.getClass().getName().indexOf("LayeredHighlightInfo") > -1) { 
            // Avoid allocing unless we need it. 
            final Rectangle a = this.component.getBounds(); 
            final Insets insets = this.component.getInsets(); 
            a.x = insets.left; 
            a.y = insets.top; 
            // a.width -= insets.left + insets.right + 100; 
            a.height -= insets.top + insets.bottom; 
            final Highlighter.HighlightPainter p = info.getPainter(); 
            p.paint(g, info.getStartOffset(), info.getEndOffset(), a, this.component); 
           } 
          } 
         } 
    
         @Override 
         public void removeAllHighlights() { 
          textPane.repaint(0, 0, textPane.getWidth(), textPane.getHeight()); 
          super.removeAllHighlights(); 
         } 
        } 
    } 
    
  • Répondre

    3

    http://tips4java.wordpress.com/2008/10/29/line-painter/

    Je pense que c'est ce que vous recherchez. J'ai pris cette LinePainter classe et copiais votre constructeur sur dans une méthode principale, a pris vos pièces surligneur et a ajouté un new LinePainter(textPane); fonctionne comme un charme

    +0

    Merci beaucoup ... ça ressemble vraiment ça fonctionne comme un charme. – Preachie

    +0

    De rien. :) – spedsal

    1

    Je pense que cela pourrait être difficile à réaliser en utilisant surligneurs - Je ne pense pas que ce soit pour quoi ils ont été conçus. Vous devrez peut-être le faire avec le code de peinture personnalisé:

    import java.awt.Color; 
    import java.awt.Graphics; 
    import java.awt.Rectangle; 
    
    import javax.swing.JFrame; 
    import javax.swing.JTextPane; 
    import javax.swing.text.BadLocationException; 
    
    public class HighlightLineTest { 
        private static class HighlightLineTextPane extends JTextPane { 
         public HighlightLineTextPane() { 
          // Has to be marked as transparent so the background is not replaced by 
          // super.paintComponent(g); 
          setOpaque(false); 
         } 
    
         @Override 
         protected void paintComponent(Graphics g) { 
          g.setColor(getBackground()); 
          g.fillRect(0, 0, getWidth(), getHeight()); 
          try { 
           Rectangle rect = modelToView(getCaretPosition()); 
           if (rect != null) { 
            g.setColor(Color.CYAN); 
            g.fillRect(0, rect.y, getWidth(), rect.height); 
           } 
          } catch (BadLocationException e) { 
          } 
          super.paintComponent(g); 
         } 
    
         @Override 
         public void repaint(long tm, int x, int y, int width, int height) { 
          // This forces repaints to repaint the entire TextPane. 
          super.repaint(tm, 0, 0, getWidth(), getHeight()); 
         } 
        } 
    
        public static void main(String[] args) { 
         JFrame frame = new JFrame("Highlight test"); 
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
         frame.add(new HighlightLineTextPane()); 
         frame.setBounds(100, 100, 300, 400); 
         frame.setVisible(true); 
        } 
    } 
    
    2

    Ci-dessous le code pour extraire le texte de la ligne en cours. Vous pouvez utiliser la même logique pour obtenir des indices nécessaires et mettre en évidence le texte

    private String getCurrentEditLine() { 
         int readBackChars = 100; 
         int caretPosition = scriptEditor.getCaretPosition(); 
    
         if (caretPosition == 0) { 
          return null; 
         } 
    
         StyledDocument doc = scriptEditor.getStyledDocument(); 
    
         int offset = caretPosition <= readBackChars ? 0 : caretPosition 
           - readBackChars; 
    
         String text = null; 
         try { 
          text = doc.getText(offset, caretPosition); 
         } catch (BadLocationException e) { 
         } 
    
         if (text != null) { 
          int idx = text.lastIndexOf("\n"); 
          if(idx != -1) { 
           return text.substring(idx); 
          }else { 
           return text; 
          } 
         } 
    
         return null; 
        } 
    
    Questions connexes