【问题标题】:Multiple, but limited, CheckBoxes in FXML/JavaFXFXML/JavaFX 中的多个但有限的复选框
【发布时间】:2015-08-13 03:20:54
【问题描述】:

我正在尝试找到一种使用复选框的方法,以允许用户从三项列表中选择两项,然后禁用剩余的复选框,直到取消选中其他复选框。我在所有三个复选框上都附加了一个 ChangeListener,因此我可以在选择两个复选框时进行注册,但我不知道如何定位“其他”框/框以禁用/启用它们。

ChangeListener checkboxlistener = new ChangeListener() {
int i = 0;
        @Override
        public void changed(ObservableValue observable, Object oldValue, Object newValue) {


            if((boolean) observable.getValue() == true) {

                i++;
                System.out.println(i);
            } else {
                i--;
                System.out.println(i);
            }
            if(i == 2) {
                //What should I put here, if anything?//
            }
        }

};
    checkbox1.selectedProperty().addListener(checkboxlistener);
    checkbox2.selectedProperty().addListener(checkboxlistener);
    checkbox3.selectedProperty().addListener(checkboxlistener);

}

【问题讨论】:

    标签: checkbox javafx listener


    【解决方案1】:

    保留选中复选框和未选中复选框的集合。为每个复选框的 selectedProperty 添加一个侦听器,并确保在选择更改时它位于正确的集合中。

    然后你可以只观察选中复选框集合的大小,并相应地更新所有未选中复选框的disable状态。

    这是一个例子:

    MultipleCheckBoxExampleController.java:

    package multiplecheckbox;
    
    import javafx.beans.binding.Bindings;
    import javafx.beans.binding.IntegerBinding;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableSet;
    import javafx.fxml.FXML;
    import javafx.scene.control.Button;
    import javafx.scene.control.CheckBox;
    
    public class MultipleCheckBoxExampleController {
        @FXML
        private CheckBox checkBox1 ;
        @FXML
        private CheckBox checkBox2 ;
        @FXML
        private CheckBox checkBox3 ;
        @FXML
        private Button submitButton ;
    
        private ObservableSet<CheckBox> selectedCheckBoxes = FXCollections.observableSet();
        private ObservableSet<CheckBox> unselectedCheckBoxes = FXCollections.observableSet();
    
        private IntegerBinding numCheckBoxesSelected = Bindings.size(selectedCheckBoxes);
    
        private final int maxNumSelected =  2; 
    
        public void initialize() {
            configureCheckBox(checkBox1);
            configureCheckBox(checkBox2);
            configureCheckBox(checkBox3);
    
            submitButton.setDisable(true);
    
            numCheckBoxesSelected.addListener((obs, oldSelectedCount, newSelectedCount) -> {
                if (newSelectedCount.intValue() >= maxNumSelected) {
                    unselectedCheckBoxes.forEach(cb -> cb.setDisable(true));
                    submitButton.setDisable(false);
                } else {
                    unselectedCheckBoxes.forEach(cb -> cb.setDisable(false));
                    submitButton.setDisable(true);
                }
            });
    
    
        }
    
        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);
                }
    
            });
    
        }
    
    }
    

    MultipleCheckBoxExample.fxml:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.VBox?>
    <?import javafx.scene.control.CheckBox?>
    <?import javafx.scene.control.Button?>
    <?import javafx.geometry.Insets?>
    
    <VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="multiplecheckbox.MultipleCheckBoxExampleController"
         alignment="center" spacing="5">
    
        <padding>
            <Insets top="10" bottom="10" left="10" right="10" />
        </padding>
    
        <CheckBox fx:id="checkBox1" text="Choice 1" />
        <CheckBox fx:id="checkBox2" text="Choice 2" />
        <CheckBox fx:id="checkBox3" text="Choice 3" />
        <Button fx:id="submitButton" text="Submit" />
    </VBox>
    

    Main.java:

    package multiplecheckbox;
    
    import javafx.application.Application;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.layout.VBox;
    import javafx.fxml.FXMLLoader;
    
    
    public class Main extends Application {
        @Override
        public void start(Stage primaryStage) {
            try {
                VBox root = FXMLLoader.load(getClass().getResource("MultipleCheckBoxExample.fxml"));
                Scene scene = new Scene(root,400,400);
                primaryStage.setScene(scene);
                primaryStage.show();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    【讨论】:

    • 谢谢,我会测试一下。有两件事,首先,如果我使用 FXML,我是尝试将这段代码放入控制器的初始化方法中,还是将其放在其他地方?似乎它会进入主课。其次,这是否与 SceneBuilder 相得益彰?因为我从来没有将在 SceneBuilder 之外创建的 UI 元素与在其中创建的 UI 元素混合在一起。
    • 您可以在 FXML 中创建复选框,然后在初始化方法中使用处理程序等配置它们。等我回到电脑前,我会更新这个例子。
    • 另外,在将其复制到 Netbeans(到新 FXML 项目的主类中)后,它会运行并给我三个复选框,但允许我选择所有三个
    • 非常感谢。我不知道你是不是一个 DnD 的人,但我正在尝试学习这个技巧,以便我可以准确地限制玩家在创建角色时可以选择的专长数量,也许我什至可以将其重新用于设备重量库存跟踪器。
    • 更新了使用 FXML 的示例:它与以前几乎相同。我测试了它,它工作正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    相关资源
    最近更新 更多