如何访问类中创建的多个ToggleButtons?

时间:2015-02-16 12:19:46

标签: arrays javafx togglebutton

我有一个使用SceneBuilder制作的GridPane(6x9)。在GridPane内部,我使用以下代码在控制器中创建了50个ToggleButtons:

@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]。当我“关闭”一个按钮时,该数字应该从数组中删除。如何添加和删除这些值?我应该在哪里有这个代码?在initialize方法里面?

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

  3. 谢谢!

2 个答案:

答案 0 :(得分:1)

我建议在控制器中创建和公开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);

答案 1 :(得分:0)

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

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

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