java如何通过JavaFX中的单选按钮对最大可选复选框进行约束?
请看下面的图片,你会理解我的应用程序的布局
我希望能够动态选择可选择的CheckBox
(启用下拉菜单)数量(固定数量)。我想通过这3 RadioButton
来实现这一点
在垂直模式下,必须选择所有4CheckBox
(不少于)。在混合模式下,只有2CheckBox
可用(不能多也不能少)。在水平模式下,只能选择1CheckBox
(不能选择更多)。重要的是,用户能够选择特定的组合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
操纵它们
# 1 楼答案
您可以在所有
RadioButton
上设置一个侦听器,当选择一个侦听器时,禁用或启用每个ComboBox
/CheckBox
节点的容器下面是一个示例应用程序,演示了这一点。我用纯Java(没有FXML)构建UI,只是为了将所有内容保存在一篇文章中。重要的部分是
RadioButtons
中添加的三个侦听器有几件事需要注意。您将需要命名容器来启用/禁用适当的选择区域。在这里,它们被称为
hbSelection#
,这是我们添加复选框和组合框的地方在监听器中,您将看到我基本上只是基于
newValue
设置每个HBox的disabled属性,如果选择了RadioButton
,则设置为true
,如果未选择则设置为false
也许有一种更有效的方法来处理这个问题,但这绝对是一种方法
# 2 楼答案
我不建议硬编码
CheckBox
es/ComboBox
es和不同地方的病例计数。使用相同的值创建CheckBox
es/ComboBox
es和修改所选CheckBox
es的允许数量。但是,这会妨碍您仅在fxml中创建外观除非您希望用户有一些相当混乱的行为,否则您需要允许用户选择少于所需数量的
CheckBox
,因为在取消选择时,您无法真正判断要选择哪个CheckBox
。您可以禁用/启用用于提交表单的按钮或一些类似控件