mmgro27
mmgro27

Reputation: 515

How to move the cursor position in a JTextField

I have a JTextField inputTextField and I would like the symbol to be added to the text field at the cursor position when the orButton is pressed. The method below works but after the button is pressed the cursor appears at the end of the field instead of at the position it was before the button is pressed.

How can I set the cursor to move back to its previous position?

private void orButtonActionPerformed(java.awt.event.ActionEvent evt)                                          
    {
        int caretPosition = inputTextField.getCaretPosition();
        String currentText = inputTextField.getText();
        String newText = currentText.substring(0, caretPosition) + 
        "∨" + currentText.substring(caretPosition, currentText.length());

        inputTextField.setText(newText);
        inputTextField.requestFocus();
    }                                        

I thought setCaretPosition() might be what I was looking for but it didn't work.

Upvotes: 2

Views: 18433

Answers (3)

Roberto Attias
Roberto Attias

Reputation: 1903

what resets the position of the caret is the setText(), not the field getting the focus. If you put the setCaretPosition() between setText() and requestFocus() it should work.

This is a working example:

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

public class Test {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    JTextField tf = new JTextField();
    JButton b = new JButton("button");
    tf.setText("abcdefghijklmnop");
    b.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ev) {
           int caretPosition = tf.getCaretPosition();
            String currentText = tf.getText();
            String left = currentText.substring(0, caretPosition);
            String right = currentText.substring(caretPosition, currentText.length());
            String newText = left + "v" + right;
            tf.setText(newText);
            tf.setCaretPosition(caretPosition+1);
            tf.requestFocus();
        }
    });
    JPanel p = (JPanel)f.getContentPane();
    p.setLayout(new BorderLayout());
    p.add(b, BorderLayout.EAST);
    p.add(tf, BorderLayout.CENTER);
    f.setSize(640, 400);
    f.setVisible(true);
  }
}

Upvotes: 0

Gobinath
Gobinath

Reputation: 904

setCaretPosition works as expected. You need to call this before or after calling requestFocus method. The working example is provided below:

private void orButtonActionPerformed(java.awt.event.ActionEvent evt)                                          
{
    int caretPosition = inputTextField.getCaretPosition();
    String currentText = inputTextField.getText();
    String newText = currentText.substring(0, caretPosition) + 
    "∨" + currentText.substring(caretPosition, currentText.length());

    inputTextField.setText(newText);
    inputTextField.requestFocus();
    inputTextField.setCaretPosition(caretPosition);
}  

Upvotes: 0

Axel
Axel

Reputation: 14159

setCaretPosition() should be the right method. However it seems the caret is set to position 0 again when the text field gets the focus. You could try wrapping it inside a SwingUtilities.invokeLater() call like this:

private void orButtonActionPerformed(java.awt.event.ActionEventevt) {
    final int caretPosition = inputTextField.getCaretPosition();
    String currentText = inputTextField.getText();
    String newText = currentText.substring(0, caretPosition) + 
    "∨" + currentText.substring(caretPosition, currentText.length());

    inputTextField.setText(newText);
    inputTextField.requestFocus();

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            inputTextField.setCaretPosition(caretPosition);
        }
    });
}

Note that you have to declare caretPosition as final for this to work.

Upvotes: 4

Related Questions