簡體   English   中英

JavaFX中的多重布爾綁定

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM