Issue
I have a TextField
, in which I do a check after any changes are made. I also trim away any double spaces that were typed. Problem is that after I replace text with trimmed one, Caret
position refreshes. I added calculating, so that Caret
will go to position user last input, but it's not working properly with extra spaces. My code:
EventHandler<InputEvent> fieldChangeListener = new EventHandler<InputEvent>() {
public void handle(InputEvent event) {
TextField field = (TextField) event.getSource();
int caretPos = field.getCaretPosition();
String text = field.getText();
text = text.replaceAll("\\s+", " ").trim();
field.setText(text);
field.positionCaret(caretPos);
event.consume();}};
name.addEventHandler(KeyEvent.KEY_RELEASED, fieldChangeListener);
In picture user puts cursor before word 'Friend', presses space bar and extra space will get trimmed, placing Caret
right after 'F'. If space bar will be hold longer, Caret
will be placed in the end.
Desired result: Caret placed before word 'Friend'.
How would be better to do that?
Solution
The reason why the caret position is not working as expected is because you are not reducing the caret position when there is multiple space in the string. You should remove the caret position by the amount of removed multiple spaces.
In the code below, I check if the string has at least double spaces and if it does then i remove the spaces and also reduce the caret position by the number of spaces removed from the string.
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.InputEvent;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Miner extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
AnchorPane pane = new AnchorPane();
TextField tf = new TextField("HELLO FRIEND");
int CaretPos = tf.getCaretPosition();
System.out.println("CaretPos = " + CaretPos);
pane.getChildren().add(tf);
EventHandler<InputEvent> fieldChangeListener = new EventHandler<InputEvent>() {
public String AtLeastDoubleSpace = " ";
public void handle(InputEvent event) {
TextField field = (TextField) event.getSource();
String text = field.getText();
String originalString = text;
int caretPos;
if(text.contains(AtLeastDoubleSpace)) {
caretPos = field.getCaretPosition();
text = text.replaceAll("\\s+"," ").trim();
field.setText(text);
int spacesRemoved = originalString.length() - text.length();
field.positionCaret(caretPos - spacesRemoved);
event.consume();
} else {
caretPos = field.getCaretPosition();
field.setText(text);
field.positionCaret(caretPos);
event.consume();
}
}};
tf.addEventHandler(KeyEvent.KEY_RELEASED, fieldChangeListener);
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I provided this solution depending upon my understanding to the question you provided. Let me know, if you need any further help.
Answered By - lambad
Answer Checked By - David Marino (JavaFixing Volunteer)