1

I've got a model class with a decimal RGB value member (i.e. value 16777215, #FFFFFF, which is white) in IntegerProperty type. Now I need to bind it to ColorPicker control but it needs ObservableValue<Color> and I don't know how to "convert" the IntegerProperty to ObservableValue<Color> and successfully bind it to the ColorPicker.

Any good idea for implementing that?

Thanks in advance.

Jackson Ming Hu
  • 1,681
  • 2
  • 14
  • 23
  • 1
    Since none of the properties is a `Property` so a bidirectional binding is out of question. Binding the value property of the color picker will result in problems though, since since assigning a bound property results in an exception so interacting with the colorpicker gui is problematic. You could use listeners for both properties to set the other though... – fabian Mar 13 '18 at 12:19
  • Do you need it to be bidirectional? – Tuom Mar 13 '18 at 13:50
  • @Tuom So far I think single-way binding is enough. – Jackson Ming Hu Mar 14 '18 at 06:40

2 Answers2

2

Maybe there is a better solution, but this creates bidirectional binding of color and integer properties.

IntegerProperty intProperty = new SimpleIntegerProperty();
ObjectProperty<Color> colorProperty = colorPicker.valueProperty();

ObjectBinding<Color> colorBinding = Bindings.createObjectBinding(() -> intToColor(intProperty.get()), intProperty);
colorProperty.bind(colorBinding);
IntegerBinding intBinding = Bindings.createIntegerBinding(() -> colorToInt(colorProperty.get()), colorProperty);
intProperty.bind(intBinding);

Here is a conversion from Color to int. (Inspired by method setColor of PixelWriter in WritableImage)

private int colorToInt(Color c) {
    int r = (int) Math.round(c.getRed() * 255);
    int g = (int) Math.round(c.getGreen() * 255);
    int b = (int) Math.round(c.getBlue() * 255);
    return (r << 16) | (g << 8) | b;
}

And here is a conversion from int to Color. (More about splitting of an integer)

private Color intToColor(int value) {
    int r = (value >>> 16) & 0xFF;
    int g = (value >>> 8) & 0xFF;
    int b = value & 0xFF;
    return Color.rgb(r,g,b);
}
Tuom
  • 596
  • 5
  • 19
1

Provided that you have the code nailed down to convert integers to colors and vice versa (you probably have), here's the conversion part:

// I assume you have some method like this somewhere
private static Color int2color(int intVal) {
    return ...
}

// your property
SimpleIntegerProperty iob = new SimpleIntegerProperty(0);

// The conversion. Note that ObjectBinding<Color> is derived from ObservableValue<Color>
ObjectBinding<Color> colorBinding = Bindings.createObjectBinding(() -> int2color(iob.get()), iob);
mtj
  • 3,381
  • 19
  • 30