[英]Multiple Boolean Binding in JavaFX
我試圖將一個復選框綁定到多個復選框,如下所示:
private void bindPanelToPackages(CheckBox panel, CheckBox ...pkg){
BooleanProperty panelBinding = null;
BooleanBinding binder = null;
for(CheckBox p: pkg){
if(panelBinding == null){
panelBinding = p.selectedProperty();
}
else{
binder = panelBinding.and(p.selectedProperty());
}
}
if(binder != null){
panel.selectedProperty().bind(binder);
}
else if(panelBinding != null){
panel.selectedProperty().bindBidirectional(panelBinding);
}
}
我想要的是當'pkg'具有多個項目時允許雙向組綁定。 這樣,當我選擇包裝時,將自動選擇“面板”,或者如果我選擇“面板”,則將選擇/取消選擇所有“ pkg”。 我被困在:
panel.selectedProperty()。bind(binder);
並得到
“ JavaFX Application Thread” java.lang.RuntimeException:CheckBox.selected:不能設置綁定值。
因為我對“活頁夾”進行了單向綁定。 有什么辦法可以執行與此等效的操作嗎?:
panel.selectedProperty()。bindBidirectional(binder);
我似乎在文檔中找不到它,或者我不在正確的位置。 謝謝!
條件“選中所有復選框”只能表示為BooleanBinding
,而不能表示為BooleanProperty
。 基本上,問題在於沒有明確定義使該條件為false
:有許多方法可以做到這一點(即,取消選中所有復選框的任何非空子集)。 因此,您不能使用雙向綁定:您必須在兩個條件的每一個上使用偵聽器。
這是一個實現:
// must keep a reference to the Binding to prevent premature
// garbage collection:
BooleanBinding allSelected ;
private void bindPanelToPackages(CheckBox pane, CheckBox... packages) {
// BooleanBinding that is true if and only if all check boxes in packages are selected:
allSelected = Bindings.createBooleanBinding(() ->
// compute value of binding:
Stream.of(packages).allMatch(CheckBox::isSelected),
// array of thing to observe to recompute binding - this gives the array
// of all the check boxes' selectedProperty()s.
Stream.of(packages).map(CheckBox::selectedProperty).toArray(Observable[]::new));
// update pane's selected property if binding defined above changes
allSelected.addListener((obs, wereAllSelected, areAllNowSelected) ->
pane.setSelected(areAllNowSelected));
// use an action listener to listen for a direct action on pane, and update all checkboxes
// in packages if this happens:
pane.setOnAction(e ->
Stream.of(packages).forEach(box -> box.setSelected(pane.isSelected())));
}
和SSCCE:
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MultipleCheckBoxSelection extends Application {
private BooleanBinding allSelected ;
@Override
public void start(Stage primaryStage) {
CheckBox selectAll = new CheckBox("Select all");
int numBoxes = 5 ;
CheckBox[] boxes = IntStream
.rangeClosed(1, numBoxes)
.mapToObj(i -> new CheckBox("Item "+i))
.toArray(CheckBox[]::new);
bindPanelToPackages(selectAll, boxes);
VBox root = new VBox(10, selectAll);
root.setStyle("-fx-padding: 15;");
Stream.of(boxes).forEach(box -> box.setStyle("-fx-padding: 0 0 0 10;"));
Stream.of(boxes).forEach(root.getChildren()::add);
Scene scene = new Scene(root, 250, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
private void bindPanelToPackages(CheckBox pane, CheckBox... packages) {
// BooleanBinding that is true if and only if all check boxes in packages are selected:
allSelected = Bindings.createBooleanBinding(() ->
// compute value of binding:
Stream.of(packages).allMatch(CheckBox::isSelected),
// array of thing to observe to recompute binding - this gives the array
// of all the check boxes' selectedProperty()s.
Stream.of(packages).map(CheckBox::selectedProperty).toArray(Observable[]::new));
// update pane's selected property if binding defined above changes
allSelected.addListener((obs, wereAllSelected, areAllNowSelected) ->
pane.setSelected(areAllNowSelected));
// use an action listener to listen for a direct action on pane, and update all checkboxes
// in packages if this happens:
pane.setOnAction(e ->
Stream.of(packages).forEach(box -> box.setSelected(pane.isSelected())));
}
public static void main(String[] args) {
launch(args);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.