Issue
I'm using a TextField
to display the path of a directory the user has opened in my application.
Currently, if the path can't fit inside the TextField
, upon focusing away/clicking away from this control, it looks like as if the path has become truncated:
I want the behaviour of TextField
set such that when I focus away from it, the path shown inside automatically scrolls to the right and the user is able to see the directory they've opened. I.e. something like this:
How can I achieve this? I've tried adapting the answer given from here
as follows in initialize()
method in my FXML Controller
class:
// Controller class fields
@FXML TextField txtMoisParentDirectory;
private String moisParentDirectory;
// ...
txtMoisParentDirectory.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldStr, String newStr) {
moisParentDirectory = newStr;
txtMoisParentDirectory.selectPositionCaret(moisParentDirectory.length());
txtMoisParentDirectory.deselect();
}
});
However it doesn't work.
Solution
Your problem is based on two events, the length of the text entered and the loss of focus, so to solve it I used the properties textProperty()
and focusedProperty()
and here is the result :
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Launcher extends Application{
private Pane root = new Pane();
private Scene scene;
private TextField tf = new TextField();
private TextField tft = new TextField();
private int location = 0;
@Override
public void start(Stage stage) throws Exception {
scrollChange();
tft.setLayoutX(300);
root.getChildren().addAll(tft,tf);
scene = new Scene(root,400,400);
stage.setScene(scene);
stage.show();
}
private void scrollChange(){
tf.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
location = tf.getText().length();
}
});
tf.focusedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if(!newValue){
Platform.runLater( new Runnable() {
@Override
public void run() {
tf.positionCaret(location);
}
});
}
}
});
}
public static void main(String[] args) {
launch(args);
}
}
And concerning the Platform.runLater
I added it following this answer Here I don't know why it does not work without it, good luck !
Answered By - Bo Halim
Answer Checked By - Marilyn (JavaFixing Volunteer)