java - 如何通过 JavaFX 中的单选按钮对最大可选复选框进行限制?

标签 java javafx radio-group

请看下面的图片,您就会了解我的应用程序的布局。

enter image description here

我希望能够动态选择有多少个CheckBox(启用下拉菜单)可供选择(固定数量)。我想用这 3 个 RadioButton 来实现这一点。

在垂直模式下,必须选择所有 4 个 CheckBox(不少于)。在混合模式下,只有 2 个 CheckBox 必须可用(不能多也不能少)。在水平模式下,只需选择 1 个 CheckBox(不能选择更多)。重要的是,用户能够选择特定的组合ComboBox(例如:我们处于混合模式,选择 1 和 2 与选择 1 和 3 不同)。

解决方案

public class ConfigurationEditDialogController {

// Data Acquisition Tab

private ObservableList<String> options =
        FXCollections.observableArrayList(
                "ciao",
                "hello",
                "halo"
        );

@FXML
private PrefixSelectionComboBox<String> testBus1ComboBox = new PrefixSelectionComboBox<>();
@FXML
private PrefixSelectionComboBox<String> testBus2ComboBox = new PrefixSelectionComboBox<>();
@FXML
private PrefixSelectionComboBox<String> testBus3ComboBox = new PrefixSelectionComboBox<>();
@FXML
private PrefixSelectionComboBox<String> testBus4ComboBox = new PrefixSelectionComboBox<>();
@FXML
private CheckBox checkbox1;
@FXML
private CheckBox checkbox2;
@FXML
private CheckBox checkbox3;
@FXML
private CheckBox checkbox4;

private ObservableSet<CheckBox> selectedCheckBoxes = FXCollections.observableSet();
private ObservableSet<CheckBox> unselectedCheckBoxes = FXCollections.observableSet();

private IntegerBinding numCheckBoxesSelected = Bindings.size(selectedCheckBoxes);
private int maxNumSelected =  2;

@FXML
private RadioButton verticalMode;
@FXML
private RadioButton horizontalMode;
@FXML
private RadioButton hybridMode;


private Stage dialogStage;
private Configuration configuration;
private boolean okClicked = false;

/**
 * Initializes the controller class. This method is automatically called
 * after the fxml file has been loaded.
 */
@FXML
private void initialize() {
    testBus1ComboBox.setItems(options);
    testBus2ComboBox.setItems(options);
    testBus3ComboBox.setItems(options);
    testBus4ComboBox.setItems(options);
    configureCheckBox(checkbox1);
    configureCheckBox(checkbox2);
    configureCheckBox(checkbox3);
    configureCheckBox(checkbox4);

    numCheckBoxesSelected.addListener((obs, oldSelectedCount, newSelectedCount) -> {
        if (newSelectedCount.intValue() >= maxNumSelected) {
            unselectedCheckBoxes.forEach(cb -> cb.setDisable(true));
        } else {
            unselectedCheckBoxes.forEach(cb -> cb.setDisable(false));
        }
    });


    testBus1ComboBox.disableProperty().bind(checkbox1.selectedProperty().not());
    testBus2ComboBox.disableProperty().bind(checkbox2.selectedProperty().not());
    testBus3ComboBox.disableProperty().bind(checkbox3.selectedProperty().not());
    testBus4ComboBox.disableProperty().bind(checkbox4.selectedProperty().not());

}


private void configureCheckBox(CheckBox checkBox) {

    if (checkBox.isSelected()) {
        selectedCheckBoxes.add(checkBox);
    } else {
        unselectedCheckBoxes.add(checkBox);
    }

    checkBox.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
        if (isNowSelected) {
            unselectedCheckBoxes.remove(checkBox);
            selectedCheckBoxes.add(checkBox);
        } else {
            selectedCheckBoxes.remove(checkBox);
            unselectedCheckBoxes.add(checkBox);
        }

    });

}

FXML 文件选项卡 我想在此选项卡中实现 fabian 解决方案,但是不需要像我一样使用 fxml。

<Tab closable="false" text="Data Acquisition">
           <content>
                <GridPane prefHeight="254.0" prefWidth="404.0">
                    <columnConstraints>
                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="218.0" minWidth="10.0" prefWidth="111.0" />
                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="519.0" minWidth="10.0" prefWidth="490.0" />
                    <ColumnConstraints hgrow="SOMETIMES" maxWidth="316.0" minWidth="10.0" prefWidth="71.0" />
                    </columnConstraints>
                    <rowConstraints>
                    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                    </rowConstraints>
                    <children>
                        <Label text="Test Bus 1" GridPane.rowIndex="2" />
                        <Label text="Test Bus 2" GridPane.rowIndex="3" />
                        <Label text="Test Bus 3" GridPane.rowIndex="4" />
                        <Label text="Test Bus 4" GridPane.rowIndex="5" />
                    <PrefixSelectionComboBox fx:id="testBus1ComboBox" prefHeight="31.0" prefWidth="300.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="2" />
                    <PrefixSelectionComboBox fx:id="testBus2ComboBox" prefWidth="300.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="3" />
                    <PrefixSelectionComboBox fx:id="testBus3ComboBox" prefWidth="300.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
                    <PrefixSelectionComboBox fx:id="testBus4ComboBox" prefWidth="300.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="5" />
                    <CheckBox fx:id="checkbox1" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="2" />
                    <CheckBox fx:id="checkbox2" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="3" />
                    <CheckBox fx:id="checkbox3" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="4" />
                    <CheckBox fx:id="checkbox4" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="5" />
                    <Label text="Sample Mode" GridPane.rowIndex="1" />
                    <RadioButton fx:id="verticalMode" mnemonicParsing="false" selected="true" text="Vertical " GridPane.columnIndex="1" GridPane.rowIndex="1">
                       <toggleGroup>
                          <ToggleGroup fx:id="SampleModeGroup" />
                       </toggleGroup>
                    </RadioButton>
                    <RadioButton fx:id="hybridMode" mnemonicParsing="false" text="Hybrid" toggleGroup="$SampleModeGroup" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" />
                    <RadioButton fx:id="horizontalMode" mnemonicParsing="false" text="Horizontal" toggleGroup="$SampleModeGroup" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.rowIndex="1" />
                    </children>
                </GridPane>
           </content>
        </Tab>

我只能使用 private int maxNumSelected = 2; 手动设置允许的最大(但不是最小)数字。不过我想通过 RadioButton 来操作它们。

最佳答案

您可以在所有 RadioButton 上设置监听器选择其中之一后,禁用或启用每个 ComboBox 的容器/CheckBox节点。

这是一个演示这一点的示例应用程序。我使用纯 Java(无 FXML)构建了 UI,只是为了将所有内容都保存在一篇文章中。重要的部分是添加到RadioButtons中的三个监听器。 .

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {

        // Root layout
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Radio buttons
        HBox hbRadios = new HBox(10);
        hbRadios.setAlignment(Pos.CENTER);
        ToggleGroup tglRadioSelections = new ToggleGroup();
        RadioButton rdoVertical = new RadioButton("Vertical");
        RadioButton rdoHybrid = new RadioButton("Hybrid");
        RadioButton rdoHorizontal = new RadioButton("Horizontal");
        tglRadioSelections.getToggles().addAll(rdoVertical, rdoHybrid, rdoHorizontal);
        hbRadios.getChildren().addAll(rdoVertical, rdoHybrid, rdoHorizontal);

        // ComboBoxes and CheckBoxes
        VBox vbSelections = new VBox(10);
        ComboBox cbo1 = new ComboBox();
        ComboBox cbo2 = new ComboBox();
        ComboBox cbo3 = new ComboBox();
        ComboBox cbo4 = new ComboBox();
        CheckBox chk1 = new CheckBox();
        CheckBox chk2 = new CheckBox();
        CheckBox chk3 = new CheckBox();
        CheckBox chk4 = new CheckBox();

        // Create the containers for each selection group
        HBox hbSelection1 = new HBox(10);
        hbSelection1.getChildren().addAll(cbo1, chk1);
        HBox hbSelection2 = new HBox(10);
        hbSelection2.getChildren().addAll(cbo2, chk2);
        HBox hbSelection3 = new HBox(10);
        hbSelection3.getChildren().addAll(cbo3, chk3);
        HBox hbSelection4 = new HBox(10);
        hbSelection4.getChildren().addAll(cbo4, chk4);

        // Add listeners for each radio button to enable appropriate selections
        rdoVertical.selectedProperty().addListener((observableValue, oldValue, newValue) -> {
                hbSelection1.setDisable(!newValue);
                hbSelection2.setDisable(!newValue);
                hbSelection3.setDisable(!newValue);
                hbSelection4.setDisable(!newValue);
        });
        rdoHybrid.selectedProperty().addListener((observableValue, oldValue, newValue) -> {
            hbSelection1.setDisable(!newValue);
            hbSelection2.setDisable(!newValue);
            hbSelection3.setDisable(!newValue);
            hbSelection4.setDisable(newValue);
        });
        rdoHorizontal.selectedProperty().addListener((observableValue, oldValue, newValue) -> {
            hbSelection1.setDisable(!newValue);
            hbSelection2.setDisable(newValue);
            hbSelection3.setDisable(newValue);
            hbSelection4.setDisable(newValue);
        });

        // Build the scene
        vbSelections.getChildren().addAll(hbSelection1, hbSelection2, hbSelection3, hbSelection4);
        root.getChildren().addAll(hbRadios, vbSelections);
        stage.setScene(new Scene(root));

        stage.show();
    }
}

有几点需要注意。您将需要命名容器来启用/禁用适当的选择区域。这里他们被称为hbSelection# ,这是我们添加复选框和组合框的地方。

在监听器中,您会看到我基本上只是根据 newValue 设置每个 HBox 的禁用属性。这是 true如果RadioButton被选中并 false如果不是。

可能有一种更有效的方法来处理这个问题,但这绝对是一种方法。

关于java - 如何通过 JavaFX 中的单选按钮对最大可选复选框进行限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50970771/

相关文章:

java - 按钮在 fragment 中不起作用没有错误?

java - 为什么这段代码会不断出现错误, "illegal start of expression"错误指向 & 符号

java - 从数组写入可序列化对象

java - 通过JavaFx表格单元格编辑动态更改SQL数据库的方法

jquery-mobile - jquery 移动字段集宽度

java - 为什么添加 throws InterruptedException 会为 Runnable 的实现创建编译错误

java - 如何获得 JavaFX 应用程序中的主要阶段?

java - 如何将值绑定(bind)到计算结果?

javascript - 使用 getElementsByName 验证单选按钮

android - 每行带有 RadioGroup 的 ListView