Search code examples
javauser-interfacejavafxdata-bindingjavafx-bindings

JavaFX: Binding to insets


I am pretty new to JavaFX and is fascinated by the binding capability. However, I could not figure out how to bind to the margin/padding of a node.

Currently, I am trying to make a textbox (or TextField) that has an image on the left. I made a StackPane to wrap around the TextField, as well as an ImageView to that StackPane. Then I tried binding the ImageView's height property to TextField's height property, but the image does not visually look like it's inside the TextField, because it is overlapping with the TextField's borders.

I ended up modifying the binding to account for the TextField's padding.

imageView.fitHeightProperty().bind(textField.heightProperty().subtract(textField.getPadding().getTop() + textField.getPadding().getBottom()));

It is working, but the part that the paddings are not bound is making me feel uneasy, because this value is counted as a constant which is equivalent to whatever padding it has when I set the binding. Things are going to go haywire if the padding is changed again after the binding.

This is an example of the textfield I want to achieve.

Is there a better way to do it? Either a better binding method, or a totally different approach to make an UI similar to the example. The current approach is not elegant because I am also setting a fixed amount of left padding so that the TextField content does not overlap with the image.


Solution

  • You can create your own binding using Bindings.createDoubleBinding:

    imageView.fitHeightProperty().bind(Bindings.createDoubleBinding(() -> 
        textField.getHeight() - (textField.getPadding().getTop() + textField.getPadding().getBottom())
    , textField.paddingProperty(), textField.heightProperty()));
    

    If you check the method signature:

    public static DoubleBinding createDoubleBinding(Callable<Double> func, Observable... dependencies)
    

    and the javadoc of DoubleBinding:

    If One of the registered dependencies becomes invalid, this DoubleBinding is marked as invalid.

    with this binding if the height or the padding of the TextField has been changed, the binding will be re-evaluated.