Reputation: 2859
I'm trying to create BooleanBinding
which is a binded with Button#disableProperty()
. My purpose is to enable/disable the OK button when changing a TextField
from a dynamically created list of panels.
This is the initialization of the list of panels (propertiesList)
<DialogPane prefWidth="900" prefHeight="600" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1">
<fx:define>
<FXCollections fx:id="propertiesList" fx:factory="observableArrayList">
<DatabasePane name="База данни"/>
<DatabasePane name="База данни 2"/>
</FXCollections>
</fx:define>
....
<buttonTypes>
<ButtonType fx:id="okButtonType" buttonData="OK_DONE" text="Готово" />
<ButtonType buttonData="CANCEL_CLOSE" text="Затвори" />
</buttonTypes>
</DialogPane>
Each DatabasePane
contains BooleanProperty
named change
and corresponding getters and setters.
In the controller, I create a BooleanProperty
collection from the properties of the panels added in propertiesList
List<BooleanProperty> list = propertiesList.stream()
.map(pane -> pane.changeProperty())
.collect(Collectors.toList());
BooleanBinding change = Bindings.createBooleanBinding(() -> true, (BooleanProperty[]) list.toArray());
Button button = (Button) dialogPane.lookupButton(okButtonType);
button.disableProperty().bind(change.not());
java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljavafx.beans.property.BooleanProperty; ([Ljava.lang.Object; is in module java.base of loader 'bootstrap'; [Ljavafx.beans.property.BooleanProperty; is in module javafx.base of loader 'app')
If I use ObservableList
there are no errors, but only changes are made to the list itself
ObservableList<BooleanProperty> list = propertiesList.stream()
.map(pane -> pane.changeProperty())
.collect(Collectors.toCollection(() -> FXCollections.observableArrayList()));
BooleanBinding change = Bindings.createBooleanBinding(() -> true, list);
Button button = (Button) dialogPane.lookupButton(okButtonType);
button.disableProperty().bind(change.not());
Upvotes: 1
Views: 869
Reputation: 82491
List.toArray()
returns an Object[]
array not an BooleanProperty[]
array, but you cast the object array to BooleanProperty
here:
(BooleanProperty[]) list.toArray()
I recommend using Stream
's toArray
method taking a IntFunction
:
Observable[] dependencies = propertiesList.stream()
.map(DatabasePane::changeProperty)
.toArray(Observable[]::new);
BooleanBinding change = Bindings.createBooleanBinding(() -> true, dependencies);
Unless you change the Callable<Boolean>
to something more meaningfull though, you could leave out the dependencies as well, since the binding never contains a value but true
.
BooleanBinding change = Bindings.createBooleanBinding(() -> true, list);
does not work, since the list itself implements Observable
so you're passing a array containing only the list to the varargs parameter, i.e. it's equivalent to
BooleanBinding change = Bindings.createBooleanBinding(() -> true, new Observable []{ list });
and the only InvalidationListener
that is added is added to the list itself, not to it's contents.
Upvotes: 2