Статьи

Кнопка выбора: использовать кнопки-переключатели в качестве переключателей

Для MQTT.fx я хотел использовать ToggleButtons, например, чтобы выбрать декодирование сообщения MQTT или уровень QoS:

раскодировать

QoS

Я обнаружил, что в контексте ToggleGroup ToggleButtons ведут себя не так, как RadioButtons, с точки зрения выбора / отмены выбора: в отличие от RadioButtons ToggleButtons все еще можно установить в невыбранное состояние.

RadioButton расширяет ToggleButton и переопределяет fire () (который вызывается, когда пользовательский жест указывает на то, что событие для этой ButtonBase должно произойти, иначе «кнопка была нажата»):
Переключатель:

1
2
3
4
5
6
@Override public void fire() {
  // we don't toggle from selected to not selected if part of a group
  if (getToggleGroup() == null || !isSelected()) {
    super.fire();
  }
}

Кнопка-переключатель:

1
2
3
4
@Override public void fire() {
  setSelected(!isSelected());
  fireEvent(new ActionEvent());
}

В ToogleGroup кнопки ToggleButtons должны вести себя как RadioButtons, поэтому, ИМХО, это ошибка, заслуживающая запроса извлечения для ToggleButton & # 5587; & # 56841;

Один из способов справиться с этим — создать собственное расширение ToggleButton, реализующее fire () по отношению к RadioButton.
Но мне больше нравится добавлять поведение в существующие элементы управления.
Это мой трюк для изменения поведения по умолчанию, добавив фильтры ко всем кнопкам ToogleButtonGroup, использующим нежелательные события MouseEvents:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class JavaFXUtil {
 
    private static JavaFXUtil me;
 
    private JavaFXUtil() {
    }
 
    public static JavaFXUtil get() {
        if (me == null) {
            me = new JavaFXUtil();
        }
        return me;
    }
 
    public EventHandler<MouseEvent> consumeMouseEventfilter = (MouseEvent mouseEvent) -> {
        if (((Toggle) mouseEvent.getSource()).isSelected()) {
            mouseEvent.consume();
        }
    };
 
    public void addAlwaysOneSelectedSupport(final ToggleGroup toggleGroup) {
        toggleGroup.getToggles().addListener((Change<? extends Toggle> c) -> {
            while (c.next()) {
                for (final Toggle addedToggle : c.getAddedSubList()) {
                    addConsumeMouseEventfilter(addedToggle);
                }
            }
        });
        toggleGroup.getToggles().forEach(t -> {
            addConsumeMouseEventfilter(t);
        });
    }
 
    private void addConsumeMouseEventfilter(Toggle toggle) {
        ((ToggleButton) toggle).addEventFilter(MouseEvent.MOUSE_PRESSED, consumeMouseEventfilter);
        ((ToggleButton) toggle).addEventFilter(MouseEvent.MOUSE_RELEASED, consumeMouseEventfilter);
        ((ToggleButton) toggle).addEventFilter(MouseEvent.MOUSE_CLICKED, consumeMouseEventfilter);
    }
 
}
01
02
03
04
05
06
07
08
09
10
11
12
13
public class ButtonDemoController {
    @FXML
    private ToggleGroup g2;
 
    @FXML
    private ToggleGroup g3;
 
    public void initialize() {
        JavaFXUtil.get().addAlwaysOneSelectedSupport(g2);
        JavaFXUtil.get().addAlwaysOneSelectedSupport(g3);
    }
 
}

buttonofchoice

Пример кода на GitHub .

Ссылка: Кнопка выбора: используйте ToggleButtons как RadioButtons от нашего партнера JCG Дженса Детерса в блоге JavaFX Delight .