Reputation: 2211
When you create a TextArea, you can listen to its "focusedProperty".
But if the user touch the inner scrollBar of the TextArea (if it's too small), the focus of the TextArea is lost (since the scrollBar has the focus).
But as far as I am concerned, the TextArea is still having the focus because the scrollBar are part or the TextArea and there's even no way of accessing them.
How can I hack the textArea so that I would detect when the user is using the scrollBar? I want to hack/create a focusedProperty that will return true when the user is typing text or using the scrollBar.
Upvotes: 1
Views: 336
Reputation: 6537
Here is a variation on @James_D's answer, in case you need to be able to obtain the focus
binding from his answer without having a reference to the scene, e.g. if you need to set up the bindings before the text area is added to the scene, are implementing a library, or just want to have your code less entangled.
This solution uses the EasyBind library for convenient selection of nested property (selecting focusOwnerProperty
from the sceneProperty
).
public static Binding<Boolean> containsFocus(Node node) {
return EasyBind.monadic(node.sceneProperty())
.flatMap(Scene::focusOwnerProperty)
.map(owner -> {
for (Node n = owner; n != null; n = n.getParent()) {
if (n == node) return true ;
}
return false ;
})
.orElse(false); // when node.getScene() is null
}
Upvotes: 1
Reputation: 209225
Observe the Scene
's focusOwner
property, and create a BooleanBinding
that is true if it is a descendant of the text area and false otherwise:
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TextAreaFocusTest extends Application {
@Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
IntStream.rangeClosed(1, 200).forEach(i -> textArea.appendText(" "));
IntStream.rangeClosed(1, 80).forEach(i -> textArea.appendText("\nLine "+i));
Label label = new Label();
TextField textField = new TextField();
VBox root = new VBox(10, textArea, textField, label);
Scene scene = new Scene(root, 400, 400);
BooleanBinding focus = Bindings.createBooleanBinding(() -> {
for (Node n = scene.getFocusOwner(); n!= null ; n=n.getParent()) {
if (n == textArea) return true ;
}
return false ;
}, scene.focusOwnerProperty());
label.textProperty().bind(Bindings.when(focus).then("Focused").otherwise("Not Focused"));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 1