如何访问在 class 中创建的多个切换按钮?

How can I access multiple ToggleButtons created in a class?

我有一个用 SceneBuilder 制作的 GridPane (6x9)。在该 GridPane 中,我使用以下代码在我的控制器中创建了 50 个切换按钮:

@FXML
private void initialize() {
    Font numbersFont = new Font("Arial", 10);
    for (int y = 0; y < 9; y++){
        for (int x = 1; x < 7; x++) {
            Integer buttonId = (y * 6) + x;
            if (buttonId == 51) {break;}
            ToggleButton tb = new ToggleButton(Integer.toString(buttonId));
            tb.setId("tb_" + Integer.toString(buttonId));
            tb.setFont(numbersFont);
            tb.setPrefSize(27, 27);
            tb.setAlignment(Pos.CENTER);
            tb.selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                    boolean isSelected = newValue;
                    System.out.println(isSelected);
                }
            });
            numbersGrid.add(tb, x - 1, y);
        }
    }
}

在我的 MainApp.java 中,我创建了一个整数数组:

private ObservableIntegerArray selectedNumbers = FXCollections.observableIntegerArray();

我有两个问题。

  1. 我想要用按下的 ToggleButtons 的编号更新 selectedNumbers 数组。例如,如果我按下按钮 1、13 和 25,则数组应为 [1, 13, 25]。当我 "turn off" 一个按钮时,该数字应该从数组中删除。如何添加和删除这些值?我应该在哪里获得此代码?在初始化方法中?

  2. 我有一种方法可以从 50 个可用号码(1 到 50)中随机选择 N 个号码。当用户单击一个按钮时,我希望具有该编号的 ToggleButtons 为 "turned on"。我知道如何循环,但如何访问按钮?我的意思是,我将它们命名为 tb_1、tb_2 等等。那么...我该如何称呼他们?

谢谢!

1: 不要那样使用数组。如果做那样的事情,请使用 ArrayList! 我建议使用具有 50 个布尔索引 boolean[] myArray = boolean[50]; 的数组并设置索引 truefalse.

您可以让它遍历整个数组并在初始化时使用数组的值。然后,您可以向按钮添加一个事件侦听器,以便在用户切换值时再次 运行 它。

2: 将所有按钮添加到数组中并按索引获取它们。因为它们将被引用(而不是复制),所以这对性能没有影响,也许内存使用量会增加几千位,但仅此而已。

我建议在控制器中创建并公开一个 ObservableSet<Integer>,代表一组选定的切换。使用您已有的代码,这非常简单:

public class MyController {

    private final ObservableSet<Integer> selectedToggles = FXCollections.observableSet();
    public final ObservableSet<Integer> getSelectedToggles() {
        return selectedToggles ;
    }

    @FXML
    private void initialize() {
        Font numbersFont = new Font("Arial", 10);
        for (int y = 0; y < 9; y++){
            for (int x = 1; x < 7; x++) {
                Integer buttonId = (y * 6) + x;
                if (buttonId == 51) {break;}
                ToggleButton tb = new ToggleButton(Integer.toString(buttonId));
                tb.setId("tb_" + Integer.toString(buttonId));
                tb.setFont(numbersFont);
                tb.setPrefSize(27, 27);
                tb.setAlignment(Pos.CENTER);
                tb.selectedProperty().addListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        boolean isSelected = newValue;
                        if (isSelected) {
                            selectedToggles().add(buttonId);
                        } else {
                            selectedToggles().remove(buttonId);
                        }
                    }
                });
                numbersGrid.add(tb, x - 1, y);
            }
        }
    }

}

然后在您的主应用程序(或任何您需要的地方)中,您可以检索可观察集并向其注册一个侦听器:

FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml"));
Parent parent = loader.load();
MyController controller = loader.getController();
controller.getSelectedToggles().addListener((Change<? extends Integer> change) -> {
    ObservableSet<Integer> selectedToggles = controller.getSelectedToggles();
    // process selected ids...
});

为了能够操纵切换按钮的状态(例如,将它们初始化为您的随机值),您可以让每个按钮响应可观察集中的变化。在创建切换按钮的代码中(在控制器中),添加:

// existing code:
ToggleButton tb = new ToggleButton(Integer.toString(buttonId));
tb.setId("tb_" + Integer.toString(buttonId));

// respond to changes in observable set:
selectedToggles.addListener((Change<? extends Integer> change) -> 
    tb.setSelected(selectedToggles.contains(buttonId)));

然后您可以使用

来操纵切换按钮的状态
List<Integer> initiallySelected = ... ;
controller.getSelectedToggles().clear();
controller.getSelectedToggles().addAll(initiallySelected);