Custom caret for JTextArea in Java

Description

The following code shows how to custom caret for JTextArea.

Example


/*  w  ww .  j a v a 2s.  com*/
/*
 Java Swing, 2nd Edition
 By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
 ISBN: 0-596-00408-7
 Publisher: O'Reilly 
 */
// FancyCaret.java
//Another (fancier) custom caret class.
//
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Rectangle;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultCaret;
import javax.swing.text.JTextComponent;

public class Main {
  public static void main(String args[]) {
    JFrame frame = new JFrame("FancyCaret demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextArea area = new JTextArea(8, 32);
    area.setCaret(new FancyCaret());
    area.setText("VI\tVirgin Islands \nVA      Virginia\nVT\tVermont");
    frame.getContentPane().add(new JScrollPane(area), BorderLayout.CENTER);
    frame.pack();
    frame.setVisible(true);
  }

}

class FancyCaret extends DefaultCaret {

  protected synchronized void damage(Rectangle r) {
    if (r == null)
      return;

    // give values to x,y,width,height (inherited from java.awt.Rectangle)
    x = r.x;
    y = r.y;
    height = r.height;
    // A value for width was probably set by paint(), which we leave alone.
    // But the first call to damage() precedes the first call to paint(), so
    // in this case we must be prepared to set a valid width, or else
    // paint()
    // will receive a bogus clip area and caret will not get drawn properly.
    if (width <= 0)
      width = getComponent().getWidth();

    repaint(); // calls getComponent().repaint(x, y, width, height)
  }

  public void paint(Graphics g) {
    JTextComponent comp = getComponent();
    if (comp == null)
      return;

    int dot = getDot();
    Rectangle r = null;
    char dotChar;
    try {
      r = comp.modelToView(dot);
      if (r == null)
        return;
      dotChar = comp.getText(dot, 1).charAt(0);
    } catch (BadLocationException e) {
      return;
    }

    if ((x != r.x) || (y != r.y)) {
      // paint() has been called directly, without a previous call to
      // damage(), so do some cleanup. (This happens, for example, when
      // the
      // text component is resized.)
      repaint(); // erase previous location of caret
      x = r.x; // Update dimensions (width gets set later in this method)
      y = r.y;
      height = r.height;
    }

    g.setColor(comp.getCaretColor());
    g.setXORMode(comp.getBackground()); // do this to draw in XOR mode

    if (dotChar == '\n') {
      int diam = r.height;
      if (isVisible())
        g.fillArc(r.x - diam / 2, r.y, diam, diam, 270, 180); // half
      // circle
      width = diam / 2 + 2;
      return;
    }

    if (dotChar == '\t')
      try {
        Rectangle nextr = comp.modelToView(dot + 1);
        if ((r.y == nextr.y) && (r.x < nextr.x)) {
          width = nextr.x - r.x;
          if (isVisible())
            g.fillRoundRect(r.x, r.y, width, r.height, 12, 12);
          return;
        } else
          dotChar = ' ';
      } catch (BadLocationException e) {
        dotChar = ' ';
      }

    width = g.getFontMetrics().charWidth(dotChar);
    if (isVisible())
      g.fillRect(r.x, r.y, width, r.height);
  }

}

The code above generates the following result.

Custom caret for JTextArea in Java




















Home »
  Java Tutorial »
    Swing »




Action
Border
Color Chooser
Drag and Drop
Event
Font Chooser
JButton
JCheckBox
JComboBox
JDialog
JEditorPane
JFileChooser
JFormattedText
JFrame
JLabel
JList
JOptionPane
JPasswordField
JProgressBar
JRadioButton
JScrollBar
JScrollPane
JSeparator
JSlider
JSpinner
JSplitPane
JTabbedPane
JTable
JTextArea
JTextField
JTextPane
JToggleButton
JToolTip
JTree
Layout
Menu
Timer