Click here to Skip to main content
Click here to Skip to main content

Using getMagicCaretPosition Without Getting Null Value

, 15 Mar 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
How to use getMagicCaretPosition without getting null value

Introduction

Sometimes, we need to find the exact location of the cursor (caret) in a text field or another similar control. Java provides us a set of methods to calculate it but, let’s be honest, who wants to waste a few minutes that can become days in calculating the caret position?

Back in time, about four or five days ago, I lost part of my hair and patience looking for a way to get the caret position in a JTextArea. One way was to do it with the Windows API but it’ll finish in a Windows dependent program. Another way was to calculate the current column from the offset of the current cursor position. It works but not fully, at least not for my purposes. Looking in books, internet and asking my teachers at school how to determine the caret position, I got no answers. Finally, I found the way to do it: Use the method getMagicCaretPosition() to get a Point structure with the actual position of the caret in the control.

Quick Start

As Oracle says in its Wiki, getMagicCaretPosition() gets the current caret visual location. The caret changes its position every time we write or delete a character in the control. My first error was to say ”It shouldn’t be a problem, I just need to acquire the caret position when the text changes (in the method changeUpdate(KeyEvent evt) included in DocumentListener interface at javax.swing.event)”. Why? Because when we write or delete a character in the control, the caret moves until the character is written or deleted. So, getting the caret position must be in the keyReleased event to avoid getting a null when calling the getMagicCaretPosition().

Using the Code

To see a little example, let’s make a Java project in NetBeans (7.4), add a new JFrame to the package and a JTextArea to the window. Then, implement the DocumentListener and KeyListener interfaces in the JFrame.

public class getMagicCaretPositionGUI extends JFrame implements DocumentListener, KeyListener{...}

Of course, we must override the methods included in the implemented interfaces and subscribe the JTextArea to the listeners.

public getMagicCaretPositionGUI() {
     initComponents();
     this.jTextArea1.addKeyListener(this);
     this.jTextArea1.getDocument().addDocumentListener(this);
}

@Override
public void insertUpdate(DocumentEvent e) {
     changedUpdate(e); 
}

@Override
public void removeUpdate(DocumentEvent e) {
     changedUpdate(e);
}
@Override
public void changedUpdate(DocumentEvent e) { }

@Override
public void keyTyped(KeyEvent e) { }

@Override
public void keyPressed(KeyEvent e) { }

@Override
public void keyReleased(KeyEvent e) { }

Focus on the changedUpdate(DocumentEvent e) method, let’s see what happens when we try to get the current position at this method.

@Override 
public void changedUpdate(DocumentEvent e) { 
     Point p = this.jTextArea1.getCaret().getMagicCaretPosition();
     setTitle(”Actual caret position : X: ” + p. x + ” , Y: ” + p. y);
}

If we execute the project now, every time the text on the JTextArea changes will throw an exception like Exception in thread ”AWT- EventQueue-0” java.lang.NullPointerException.... Remember, when the document changes, the caret ”disappears” until the character is written or deleted.

It must be really hard to get it at the first time (as I, expend 3 days of my life getting this). Comment the code in insertUpdate and removeUpdate; and move the code in changedUpdate to KeyReleased and try it again.

@Override
public void keyReleased(KeyEvent e) {
    Point p = this.jTextArea1.getCaret().getMagicCaretPosition();
    this.setTitle("Actual caret position: X:" + p.x + ", Y: " + p.y);
}

Now it works pretty good. Beautiful, isn’t it?

Points of Interest

Getting the caret position in the changedUpdate method is valid but you must set the caret position to 0,0 getting first the caret of the control in the constructor and setting the position with the method setMagicCaretPosition(Point p) like this:

this.jTextArea1.getCaret().setMagicCaretPosition(new Point(0, 0)); 

I discovered it 10 minutes before uploading.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Alain Peralta
Student
Mexico Mexico
Great things come from rare ideas. Wink | ;)

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.141015.1 | Last Updated 15 Mar 2014
Article Copyright 2014 by Alain Peralta
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid