Я пытаюсь практиковать связывание. Я хочу сделать окно с двумя счетчиками и просто заставить их показывать одно и то же значение.
Проблема в том, что привязка ненадежна: кажется, что счетчики перестают обновлять друг друга, если на них нажимают слишком быстро. Оба счетчика по-прежнему реагируют на щелчок, и клики правильно подсчитываются для счетчика, на который нажимают, но другой счетчик перестает обновляться и никогда не восстанавливается. И совсем не обязательно очень быстро нажимать, чтобы это вызвать.
Мой код основан на этом ответе (в настоящее время оценка 8), показывающем, как привязать счетчик к IntegerProperty. Этого ответа достаточно, чтобы вызвать поведение, с которым я борюсь, но я следил за кратким обсуждением, которое последовало под этим ответом. В нем показаны другие параметры и связанные ресурсы, в том числе подсказка по использованию .asObject() и сильные ссылки.
Я использую oracle jdk 1.8.0_251 только потому, что мне не удалось заставить javaFX работать с другими JDK, которые я пробовал. Если это имеет значение, я нахожусь в eclipse 2019-12 на Linux. Кроме того, счетчики вообще не обновляют друг друга в режиме отладки, но они работают (для начала), если я запускаю свой код.
Почему это происходит? Мои предположения:
- Я все еще страдаю от сбора мусора и т. Д.
- Что-то не поспевает за быстрым щелчком: аппаратное обеспечение моего ноутбука, ОС Linux, Eclipse, мой jdk, javafx?
Можно ли как-то защитить свой код от этого? Могу ли я ограничить щелчки, чтобы нажатый счетчик реагировал на щелчки только в том случае, если они достаточно медленные, чтобы сохранить привязку?
Пожалуйста, дайте мне знать, если описанное поведение непонятно, и я загружу запись экрана на YouTube или что-то в этом роде.
public class BindTwoSpinners extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
// Set up the topSpinner
Spinner<Integer> topSpinner = new Spinner<Integer> (1,12,1);
topSpinner.setEditable(true);
ObjectProperty<Integer> topObjectProp = new SimpleObjectProperty<>(1);
IntegerProperty topIntegerProperty = IntegerProperty.integerProperty(topObjectProp);
topSpinner.getValueFactory().valueProperty().bindBidirectional(topObjectProp);
// Set up the bottomSpinner
Spinner<Integer> bottomSpinner = new Spinner<Integer> (1,12,1);
bottomSpinner.setEditable(true);
ObjectProperty<Integer> bottomObjectProp = new SimpleObjectProperty<>(1);
IntegerProperty bottomIntegerProperty = IntegerProperty.integerProperty(bottomObjectProp);
bottomSpinner.getValueFactory().valueProperty().bindBidirectional(bottomObjectProp);
// Need to keep the reference as bidirectional binding uses weak references
// https://docs.oracle.com/javase/8/javafx/api/javafx/beans/property/IntegerProperty.html#bindBidirectional-javafx.beans.property.Property-
ObjectProperty<Integer> topIntegerPropertyAsObject = topIntegerProperty.asObject();
ObjectProperty<Integer> bottomIntegerPropertyAsObject = bottomIntegerProperty.asObject();
// Bind the two spinners
bottomSpinner.getValueFactory().valueProperty(). bindBidirectional(topIntegerPropertyAsObject);
VBox root = new VBox(10, topSpinner, bottomSpinner);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}