1

Suppose a JavaFX CustomControl node that contains, say, two TextFields.

If any of these TextFields has the focus, then CustomControl.isFocused() should return true. If none of them has focus, then CustomControl.isFocused() should return false.

How do I do that?

Marcelo Glasberg
  • 29,013
  • 23
  • 109
  • 133
  • See [*Focus Listener for JavaFX Nodes*](https://stackoverflow.com/q/21798183/230513). – trashgod Aug 03 '17 at 23:33
  • @trashgod That post is about attaching focus listeners. That's not my problem. I have a CustomControl which is COMPOSED by these two text-fields. Think about a tree that is to be considered focused if any of its leaves is focused. – Marcelo Glasberg Aug 03 '17 at 23:52
  • I believe you can use delegation, as suggested below. – trashgod Aug 04 '17 at 00:59

2 Answers2

1

As your CustomControl uses composition, you can delegate to the focus properties of each TextField. Given two instances,

private final TextField tf1 = new TextField("One");
private final TextField tf2 = new TextField("Two");

The implementation of an instance method isFocused() is then straightforward:

private boolean isFocused() {
    return tf1.isFocused() | tf2.isFocused();
}

Add focus listeners as shown here to see the effect.

tf1.focusedProperty().addListener((Observable o) -> {
    System.out.println(isFocused());
});
tf2.focusedProperty().addListener((Observable o) -> {
    System.out.println(isFocused());
});

This can't be done. The whole problem is that isFocused() is final in Node.

It seems you wanted to override isFocused() in CustomControl, but that is not possible for a final method and it would violate the notion of a single component having focus. As CustomControl is a composite, you'll need to manage focus internally. You may want to use a custom FocusModel as seen in ListView.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • This can't be done. The whole problem is that `isFocused()` is `final` in `Node`. – Marcelo Glasberg Aug 04 '17 at 03:34
  • Ah, you want to override `isFocused()` in `CustomControl`; more above. – trashgod Aug 04 '17 at 08:36
  • I'm not sure I understand the concept of a FocusModel. I couldn't find any explanation of what a FocusModel is and how it's supposed to be used. – Marcelo Glasberg Aug 04 '17 at 22:44
  • It's just a way to manage focus among an arbitrary number of items; here's the `ListView` [implementation](http://grepcode.com/file/repo1.maven.org/maven2/net.java.openjfx.backport/openjfx-78-backport/1.8.0-ea-b96.1/javafx/scene/control/ListView.java#ListView.ListViewFocusModel); IMO, your `CustomControl` should return the default, `false`, as it is not focusable _per se_. What class do you expect to use the result of `isFocused()`, above, or the `aggregatedFocusProperty`, [here](https://stackoverflow.com/a/45511677/230513)? – trashgod Aug 05 '17 at 01:32
  • I have experience with the way focus works with Web Components, where if an internal element has focus, the containing component as a whole is considered to have focus. I assumed that Javafx focus implementation would have the same principle, but it seems that's not the case. – Marcelo Glasberg Aug 05 '17 at 01:55
  • Ah, like [this](https://stackoverflow.com/a/32575793/230513). This [example](https://stackoverflow.com/q/31909941/230513) illustrates the default traversal policy; note how some controls change appearance when focused for input, while others do not; see [`Node::requestFocus`](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#requestFocus--) for more. – trashgod Aug 05 '17 at 02:26
1

Try one line solution:

public BooleanBinding aggregatedFocusProperty() {
   return Bindings.or(field1.focusedProperty(), field2.focusedProperty());
}

Now on a client side you may listen this aggregated focus property.

Dmytro Maslenko
  • 2,247
  • 9
  • 16