If you don't require all the features of the region's background
—image, fills, etc.— and a solid color will suffice, also consider binding the color picker's value property to the fill color of a suitable Shape
that fills the region. Based on the examples seen here, the variation below illustrates a ColorPane
that renders a Rectangle
whose size is bound to the enclosing Pane
and whose color is bound to an ObjectProperty<Color>
holding the rectangle's color. A similar arrangement is made for the foreground Circle
. One benefit is that a custom color updates live as the the controls are adjusted. Several related examples are collected here.

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.NumberBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
/**
* @see https://stackoverflow.com/q/72583321/230513
* @see https://stackoverflow.com/a/70312046/230513
*/
public class ColorTest extends Application {
private final class ColorPane extends Pane {
public static final Color bgColor = Color.BLUE;
public static final Color fgColor = Color.CYAN;
private final Rectangle r = new Rectangle();
private final Circle c = new Circle(8, fgColor);
private final ObjectProperty<Color> bg = new SimpleObjectProperty<>(bgColor);
private final ObjectProperty<Color> fg = new SimpleObjectProperty<>(fgColor);
private final InvalidationListener listener = (o) -> update();
public ColorPane() {
this.setPrefSize(256, 256);
r.widthProperty().bind(this.widthProperty());
r.heightProperty().bind(this.heightProperty());
r.setFill(bgColor);
this.getChildren().add(r);
c.centerXProperty().bind(widthProperty().divide(2));
c.centerYProperty().bind(heightProperty().divide(2));
NumberBinding diameter = Bindings.min(widthProperty(), heightProperty());
c.radiusProperty().bind(diameter.divide(2).subtract(diameter.divide(10)));
this.getChildren().add(c);
bg.addListener(listener);
fg.addListener(listener);
}
private void update() {
r.setFill(bg.get());
c.setFill(fg.get());
}
public ObjectProperty<Color> bgProperty() {
return bg;
}
public ObjectProperty<Color> fgProperty() {
return fg;
}
}
private Pane createControlPane(ColorPane view) {
ColorPicker bgPicker = new ColorPicker(view.bgProperty().get());
bgPicker.setTooltip(new Tooltip("Background color."));
view.bgProperty().bindBidirectional(bgPicker.valueProperty());
ColorPicker fgPicker = new ColorPicker(view.fgProperty().get());
fgPicker.setTooltip(new Tooltip("Foreground color."));
view.fgProperty().bindBidirectional(fgPicker.valueProperty());
return new VBox(16, bgPicker, fgPicker);
}
@Override
public void start(Stage stage) {
var root = new BorderPane();
ColorPane colorPane = new ColorPane();
root.setCenter(colorPane);
root.setLeft(createControlPane(colorPane));
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
If you do require features of the region's background
, the following example illustrates dynamically replacing the background of a GradientPane
with one that contains a LinearGradient
based on the chosen color properties. The approach has the same benefit of live custom color updates as the the controls are adjusted, illustrated above.

import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.NumberBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
/**
* @see https://stackoverflow.com/q/72583321/230513
* @see https://stackoverflow.com/a/70312046/230513
*/
public class ColorTest extends Application {
private final class GradientPane extends Pane {
public static final Color c1Color = Color.BLUE;
public static final Color c2Color = Color.CYAN;
private final Circle c = new Circle(8, c2Color);
private final ObjectProperty<Color> c1 = new SimpleObjectProperty<>(c1Color);
private final ObjectProperty<Color> c2 = new SimpleObjectProperty<>(c2Color);
private final InvalidationListener listener = (o) -> update();
public GradientPane() {
this.setPrefSize(256, 256);
c.centerXProperty().bind(widthProperty().divide(2));
c.centerYProperty().bind(heightProperty().divide(2));
NumberBinding diameter = Bindings.min(widthProperty(), heightProperty());
c.radiusProperty().bind(diameter.divide(2).subtract(diameter.divide(10)));
this.getChildren().add(c);
c1.addListener(listener);
c2.addListener(listener);
update();
}
private void update() {
Stop[] stops = new Stop[]{new Stop(0, c1.get()), new Stop(1, c2.get())};
LinearGradient lg = new LinearGradient(0.5, 0, 0.5, 1, true, CycleMethod.NO_CYCLE, stops);
this.setBackground(new Background(new BackgroundFill(lg, CornerRadii.EMPTY, Insets.EMPTY)));
stops = new Stop[]{new Stop(0, c2.get()), new Stop(1, c1.get())};
lg = new LinearGradient(0.5, 0, 0.5, 1, true, CycleMethod.NO_CYCLE, stops);
c.setFill(lg);
}
public ObjectProperty<Color> c1Property() {
return c1;
}
public ObjectProperty<Color> c2Property() {
return c2;
}
}
private Pane createControlPane(GradientPane view) {
ColorPicker bgPicker = new ColorPicker(view.c1Property().get());
bgPicker.setTooltip(new Tooltip("Color stop one."));
view.c1Property().bindBidirectional(bgPicker.valueProperty());
ColorPicker fgPicker = new ColorPicker(view.c2Property().get());
fgPicker.setTooltip(new Tooltip("Color stop two."));
view.c2Property().bindBidirectional(fgPicker.valueProperty());
VBox vBox = new VBox(10, bgPicker, fgPicker);
vBox.setPadding(new Insets(10));
return vBox;
}
@Override
public void start(Stage stage) {
var root = new BorderPane();
GradientPane colorPane = new GradientPane();
root.setCenter(colorPane);
root.setLeft(createControlPane(colorPane));
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}