如何增加ToggleGroup(例如RadioButtons)中可能的选择数量?
我在编程方面有点新,对于OOP(第二个Java项目,现在完全不熟悉)并且会喜欢任何提示或帮助。如何增加ToggleGroup(例如RadioButtons)中可能的选择数量?
我目前正在为我自己的笔&纸质游戏开发角色创作程序。我正在使用JavaFX(没有FXML,因此没有SceneBuilder)用于GUI部分。我正在JDK1.8.0_131上使用Eclipse Neon。
这是我的问题:
tl; dr:如何增加ToggleGroup中可能选择的数量?
我即将创建一个供用户选择的选项列表。该名单包含30个不同的优点,他或她可以选择提高他们的品格。所选择的选项的最大值取决于字符,大约在5之间变化。我已经实现了一个pairs(我知道HashMaps)的数组,每个条目都是由优势的名称和代表其成本的整数组成他们的价值,所以在他们的成本)。
列表本身现在应该通过
ScrollPane scrollAdv = new ScrollPane();
VBox vBoxAdv = new VBox();
scrollAdv.setContent(vBoxAdv);
Pair<String, Integer>[] listAdv = info.getAdvantages();
for (int i = 0; i < listAdv.length; i++) {
String name = listAdv[i].getKey(); // delivers the 1st entry of a pair
int costs = listAdv[i].getValue(); // delivers the 2nd entry of a pair
ToggleButton toggleButton = new ToggleButton();
toggleButton.setUserData(name);
toggleButton.setText(name + " (" + costs + ")");
vBoxAdv.getChildren().add(toggleButton);
}
请注意,我没有太在意的ToggleButtons实施,他们可以很容易地与单选按钮代替。如果我正确理解文档,两者的工作方式都是相同的。他们都使用ToggleGroup确保,只有一个选项被选中。
因此,尽管您现在可能已经猜到了,但我想要做的是让用户一次选择多个选项。我不想这样做,因此用户必须在另一个选项之后选择一个选项,同时重置其间的列表。
感谢您的阅读并提前感谢您的任何帮助或提示。
编辑:我总是可以添加一个计数器,只要选择了一个选项或取消选择,就可以刷新计数器,并阻止任何选择,但我认为应该有一个更好的解决方案。增加了ToggleGroup似乎正在使用的内置限制1。
一种方法是在达到限制时禁用其余的切换。这里有一个ToggleSet
的类,它是:
import java.util.ArrayList;
import java.util.List;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.IntegerBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.Node ;
import javafx.scene.control.Toggle;
public class ToggleSet<T extends Node & Toggle> {
private final ObservableList<T> toggles = FXCollections.observableArrayList(t -> new Observable[] {t.selectedProperty()});
private final FilteredList<T> selectedToggles = toggles.filtered(t -> ((Toggle)t).isSelected());
private final IntegerProperty maximumSelectable = new SimpleIntegerProperty(0);
private final IntegerBinding numSelected = Bindings.size(selectedToggles);
public ToggleSet(int maximumSelectable) {
this.maximumSelectable.addListener((obs, oldMax, newMax) -> {
if (newMax.intValue() < numSelected.get()) {
List<Toggle> togglesToClear = new ArrayList<>(selectedToggles.subList(0, numSelected.get() - newMax.intValue()));
togglesToClear.forEach(t -> t.setSelected(false));
}
});
setMaximumSelectable(maximumSelectable);
}
public ToggleSet() {
this(0);
}
public ObservableList<T> getSelectedToggles() {
return FXCollections.unmodifiableObservableList(selectedToggles) ;
}
public IntegerProperty maximumSelectableProperty() {
return maximumSelectable ;
}
public final int getMaximumSelectable() {
return maximumSelectableProperty().get();
}
public final void setMaximumSelectable(int maximumSelectable) {
maximumSelectableProperty().set(maximumSelectable);
}
public void addToggle(T toggle) {
if (numSelected.get() >= getMaximumSelectable()) {
toggle.setSelected(false);
}
toggles.add(toggle);
toggle.disableProperty().bind(toggle.selectedProperty().not().and(numSelected.greaterThanOrEqualTo(maximumSelectable)));
}
public void removeToggle(T toggle) {
toggles.remove(toggle);
toggle.disableProperty().unbind();
}
}
下面是一个例子测试它:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Spinner;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class ToggleSetTest extends Application {
@Override
public void start(Stage primaryStage) {
ToggleSet<ToggleButton> toggleSet = new ToggleSet<>(5);
GridPane grid = new GridPane() ;
Spinner<Integer> maxSelectedSpinner = new Spinner<>(0, 20, 5);
maxSelectedSpinner.getValueFactory().valueProperty().bindBidirectional(toggleSet.maximumSelectableProperty().asObject());
grid.add(new HBox(2, new Label("Maximum selected"), maxSelectedSpinner), 0, 0, 2, 1);
grid.addRow(1, new Label("Selection"), new Label("Include in set"));
for (int i = 1; i <= 20 ; i++) {
RadioButton button = new RadioButton("Button "+i);
CheckBox checkBox = new CheckBox();
checkBox.selectedProperty().addListener((obs, wasChecked, isNowChecked) -> {
if (isNowChecked) {
toggleSet.addToggle(button);
} else {
toggleSet.removeToggle(button);
}
});
checkBox.setSelected(true);
grid.addRow(i + 1, button, checkBox);
}
grid.setPadding(new Insets(10));
grid.setHgap(5);
grid.setVgap(2);
Scene scene = new Scene(grid);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
如果你想在相同的行为ToggleGroup
,其中前面的选择变得未选中,这是一个有点麻烦,但下面应该工作:
import java.util.ArrayList;
import java.util.List;
import javafx.beans.Observable;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node ;
import javafx.scene.control.Toggle;
public class ToggleSet<T extends Node & Toggle> {
private final ObservableList<T> toggles = FXCollections.observableArrayList(t -> new Observable[] {t.selectedProperty()});
private final ObservableList<T> selectedToggles = FXCollections.observableArrayList();
private final IntegerProperty maximumSelectable = new SimpleIntegerProperty(0);
private final ChangeListener<Boolean> toggleListener = (obs, wasSelected, isNowSelected) -> {
@SuppressWarnings("unchecked")
T toggle = (T) ((Property<?>)obs).getBean();
if (isNowSelected) {
selectedToggles.add(toggle);
ensureWithinMax();
} else {
selectedToggles.remove(toggle);
}
};
public ToggleSet(int maximumSelectable) {
this.maximumSelectable.addListener((obs, oldMax, newMax) -> ensureWithinMax());
setMaximumSelectable(maximumSelectable);
}
private void ensureWithinMax() {
if (this.maximumSelectable.get() < selectedToggles.size()) {
List<Toggle> togglesToClear = new ArrayList<>(selectedToggles.subList(0, selectedToggles.size() - this.maximumSelectable.get()));
togglesToClear.forEach(t -> t.setSelected(false));
}
}
public ToggleSet() {
this(0);
}
public ObservableList<T> getSelectedToggles() {
return FXCollections.unmodifiableObservableList(selectedToggles) ;
}
public IntegerProperty maximumSelectableProperty() {
return maximumSelectable ;
}
public final int getMaximumSelectable() {
return maximumSelectableProperty().get();
}
public final void setMaximumSelectable(int maximumSelectable) {
maximumSelectableProperty().set(maximumSelectable);
}
public void addToggle(T toggle) {
if (toggle.isSelected()) {
selectedToggles.add(toggle);
ensureWithinMax();
}
toggle.selectedProperty().addListener(toggleListener);
toggles.add(toggle);
}
public void removeToggle(T toggle) {
toggle.selectedProperty().removeListener(toggleListener);
toggles.remove(toggle);
}
}
(使用相同的测试代码。)
哇谢谢一堆!这工作非常好,感觉平稳。我要使用它的大部分内容! –
所以你希望用户能够选择一些切换按钮(或类似的),但达到一定的限制?因此,例如,他们可以选择30个中的0-5个(但不超过5个)。这是对问题的正确解释吗? –
@James_D是的,这是完全正确的。 –