允许使用ToggleGroup取消选择RadioButton

时间:2016-11-21 14:01:36

标签: javafx radio-button togglebutton

我正在尝试在JavaFX 8中获得一组RadioButton,其功能最多可以选择一个,但也可以删除任何选择。

似乎RadioButton只有在没有定义ToggleGroup的情况下才支持取消选择。但是,如果未定义ToggleGroup,则可以选择多个RadioButton

我尝试为每个按钮的onAction事件添加一个监听器:

for (final RadioButton rb : myRadioButtons) {
    rb.setToggleGroup(myToggleGroup);
    rb.setOnAction(event -> {
        if (rb.isSelected()) {
            myToggleGroup.selectToggle(null);
        }
    });
}

但是,有两个问题导致此尝试失败 - 第一个是selected属性似乎在action事件被触发之前更新,因此条件始终为true,无法选择任何按钮。 第二个问题是,如果在单击按钮时选择了按钮,则甚至不会触发action事件。

mouseClicked事件添加侦听器并不是更好,因为它只会在所选按钮更改后触发。

是否有一种简单的方法来实现一组RadioButton个,其中至少有一个被选中?或者是唯一支持使用更改侦听器等处理ToggleGroup职责的选项?

2 个答案:

答案 0 :(得分:1)

<p><?php echo $percentSKU['PercentageSales'][0]; ?></p>

public class RadioButtonTest extends Application { @Override public void start(Stage primaryStage) { Pane root = createPane(); primaryStage.setScene(new Scene(root)); primaryStage.show(); } private Pane createPane() { VBox pane = new VBox(); ToggleGroup tg = new ToggleGroup(); RadioButton b1 = new RadioButton("one"); RadioButton b2 = new RadioButton("two"); tg.getToggles().addAll(b1, b2); RadioButtonSelectionHandler b1Selection = new RadioButtonSelectionHandler(b1); b1.setOnMousePressed(b1Selection.getMousePressed()); b1.setOnMouseReleased(b1Selection.getMouseReleased()); RadioButtonSelectionHandler b2Selection = new RadioButtonSelectionHandler(b2); b2.setOnMousePressed(b2Selection.getMousePressed()); b2.setOnMouseReleased(b2Selection.getMouseReleased()); pane.getChildren().addAll(b1, b2); pane.setPrefHeight(200); pane.setPrefWidth(200); return pane; } public static void main(String[] args) { launch(args); } }

RadioButtonSelectionHandler.java

修改 这个解决方案有效,但正如@James_D建议最好使用ToggleButton(在发布此答案之前我没有看过他的评论)。我们不鼓励使用此解决方案,因为您正在寻找的功能在RadioButton设计中不存在!它在ToggleButton

来自JavaDoc的

  

与RadioButtons不同,ToggleGroup中的ToggleButtons不会尝试   强制组中至少有一个选定的ToggleButton。也就是说,如果一个   选择ToggleButton,点击它将导致它成为   未选中。使用RadioButton,单击中的所选按钮   小组没有效果。

答案 1 :(得分:0)

尽管存在用户体验问题或与设计作斗争(如其他人已经提到的),有两种选择:

  1. 子类RadioButton并覆盖其fire方法以恢复ToggleButton的行为

  2. 动态添加/删除mouseHandlers到选定的组切换

  3. 下面是两个例子(未经过正式测试!)。选项一相当简单,选项二有一些怪癖(除了可能依赖于操作系统):

    • eventHandler必须注册为eventFilter
    • 必须使用该事件
    • selectedToggle of group必须为空(取消选择切换)
    • 必须在已发布的
    • 上完成

    示例:

    public class UnselectableRadioGroup extends Application {
        /**
         * Custom radioBox with behaviour of ToggleButton. 
         */
        public static class MyRadioButton extends RadioButton {
    
            /**
             * Overridden to revert to ToggleButton behaviour.
             */
            @Override
            public void fire() {
                if (!isDisabled()) {
                    setSelected(!isSelected());
                    fireEvent(new ActionEvent());
                }
            }
    
            public MyRadioButton(String text) {
                super(text);
            }
    
        }
    
        private EventHandler<MouseEvent> mouseHandler;
    
        private void addListeners(RadioButton nv) {
            if (mouseHandler == null) {
                mouseHandler = e -> {
                    e.consume();
                    nv.getToggleGroup().selectToggle(null);
                };
            }
            nv.addEventFilter(MouseEvent.MOUSE_RELEASED, mouseHandler);
        }
    
        private void removeListeners(RadioButton ov) {
            ov.removeEventFilter(MouseEvent.MOUSE_RELEASED, mouseHandler);
        }
    
        private Parent getContent() {
            // dynamic un/register event handlers
            ObservableList<RadioButton> radios = FXCollections.observableArrayList(
                    new RadioButton("one"), new RadioButton("other"), new RadioButton("third")
                    );
            ToggleGroup group = new ToggleGroup();
            group.getToggles().addAll(radios);
    
            group.selectedToggleProperty().addListener((src, ov, nv) -> {
                if (ov instanceof RadioButton) {
                    removeListeners((RadioButton) ov);
                }
                if (nv instanceof RadioButton) {
                    addListeners((RadioButton) nv);
                }
            });
    
            VBox radioBox = new VBox(10);
            radioBox.getChildren().addAll(radios);
    
            // RadioButton reverted to ToggleButton
            ObservableList<MyRadioButton> toggles = FXCollections.observableArrayList(
                    new MyRadioButton("one"), new MyRadioButton("other"), new MyRadioButton("third")
                    );
            ToggleGroup myGroup = new ToggleGroup();
            myGroup.getToggles().addAll(toggles);
            VBox myRadioBox = new VBox(10);
            myRadioBox.getChildren().addAll(toggles);
    
            HBox content = new HBox(10, radioBox, myRadioBox);
            BorderPane pane = new BorderPane(content);
            return pane;
        }
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            Scene scene = new Scene(getContent());
            primaryStage.setScene(scene);
            //primaryStage.setTitle(FXUtils.version());
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }