Nano Hash - криптовалюты, майнинг, программирование

Два javafx Integer Spinner связаны двунаправленно: почему привязка ненадежна?

Я пытаюсь практиковать связывание. Я хочу сделать окно с двумя счетчиками и просто заставить их показывать одно и то же значение.

Проблема в том, что привязка ненадежна: кажется, что счетчики перестают обновлять друг друга, если на них нажимают слишком быстро. Оба счетчика по-прежнему реагируют на щелчок, и клики правильно подсчитываются для счетчика, на который нажимают, но другой счетчик перестает обновляться и никогда не восстанавливается. И совсем не обязательно очень быстро нажимать, чтобы это вызвать.

Мой код основан на этом ответе (в настоящее время оценка 8), показывающем, как привязать счетчик к IntegerProperty. Этого ответа достаточно, чтобы вызвать поведение, с которым я борюсь, но я следил за кратким обсуждением, которое последовало под этим ответом. В нем показаны другие параметры и связанные ресурсы, в том числе подсказка по использованию .asObject() и сильные ссылки.

Я использую oracle jdk 1.8.0_251 только потому, что мне не удалось заставить javaFX работать с другими JDK, которые я пробовал. Если это имеет значение, я нахожусь в eclipse 2019-12 на Linux. Кроме того, счетчики вообще не обновляют друг друга в режиме отладки, но они работают (для начала), если я запускаю свой код.

Почему это происходит? Мои предположения:

  1. Я все еще страдаю от сбора мусора и т. Д.
  2. Что-то не поспевает за быстрым щелчком: аппаратное обеспечение моего ноутбука, ОС 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);
}
27.12.2020

  • Двунаправленные привязки не содержат сильных ссылок друг на друга. Возможно, поскольку вы используете промежуточные свойства, что-то собирается сборщиком мусора, и поэтому привязки перестают работать. Кажется, вы понимаете это на основе комментария к коду; однако вы, похоже, не сохраняете необходимые сильные ссылки. 27.12.2020
  • @Slaw Кажется, вы понимаете это - ну, кажется - правильное слово! Насколько я понимаю, каждое свойство, которое я когда-либо использовал, уже строго упоминается в моем коде, не так ли? Я прочитаю еще немного, но было бы здорово, если бы вы смогли определить и сказать мне, чего не хватает. 27.12.2020
  • Ваши промежуточные свойства — это локальные переменные, которые выпадают из области видимости после выхода из метода start. Когда это происходит, объекты, на которые они ссылаются, подлежат сборке мусора (поскольку двунаправленные привязки используют ссылки weak). 27.12.2020
  • @Slaw Хорошо, теперь я озадачен. Я думаю, что понимаю, что вы имеете в виду, но я думал, что весь мой код находится в скобках метода start и выходит только при закрытии окна? 27.12.2020
  • Метод start завершает работу после возврата вызова primaryStage.show() в вашем коде. Метод show() не ждет закрытия окна. Теперь приложение не завершится, пока не будет закрыто последнее окно (при условии, что implicitExit равно true, как это делается по умолчанию), но это отличается от метода start. Метод start предназначен только для запуска приложения. 27.12.2020
  • @Slaw Я уже многому сегодня научился! Вы можете сказать, как решить проблему, хотя? Это вопрос использования модификаторов? Я наткнулся на кто-то использовал модификатор static и сказал, что это грязный обходной путь, который я не совсем понял, поэтому я не не пытайтесь, опасаясь неожиданных результатов. 27.12.2020
  • Для вашего примера в вашем вопросе простое сохранение ссылок на свойства в полях экземпляра, вероятно, сработает для вас. JavaFX поддерживает сильную ссылку на класс вашего приложения (это необходимо для вызова stop() при необходимости). Вы хотите избежать static, потому что это поощряет глобальное состояние, которое является злом. Если использование полей экземпляра не работает в вашем реальном коде, рассмотрите возможность предоставления минимально воспроизводимого примера, более репрезентативного для того, что вы повторно пытаюсь сделать. 27.12.2020
  • Разве вы не можете добиться того, что пытаетесь сделать, просто используя topSpinner.getValueFactory().valueProperty().bindBidirectional(bottomSpinner.getValueFactory().valueProperty())? Я думаю, что это не должно страдать от преждевременной сборки мусора слушателями. 27.12.2020
  • @James_D Так просто, и, кажется, это работает! Я пытался разорвать привязку, в несколько раз дольше, чем предыдущие попытки, они остаются связанными. В качестве бонуса они также остаются привязанными к отладке: в предыдущих попытках они никогда не связывались при отладке. И это еще до того, как я начал разбираться, почему это сработало при отладке. Мне нужно посмотреть, как именно использовать идею Slaw с полями экземпляра, если я смогу это сделать, мне, вероятно, нужно будет назвать это решением (потому что это может помочь с некоторыми другими моими болячками). Но пока спасибо чувак! Если вам нравится представитель моего голоса, пожалуйста, ответьте на него. 28.12.2020
  • @pateksan Лучший известный мне способ проверить их взлом - это позвонить System.gc() и посмотреть, работают ли они после этого. 28.12.2020
  • @Slaw В дополнение к комментарию для James_D выше, спасибо! Мне нужно будет изучить, как использовать вашу идею полей экземпляров. Кажется, это еще одна из тех основных концепций, которые мне все равно скоро нужно понять, и она может решить некоторые из моих других проблем. Так что я обязательно прочитаю, но если вы сможете предоставить хотя бы простой пример того, как я могу применить это здесь, тогда мой проект тем временем будет продолжаться. 28.12.2020
  • @James_D Я добавил это, и, похоже, это не нарушило его: topSpinner.valueProperty().addListener((obs, oldValue, newValue) -> {System.gc();}); но, пожалуйста, дайте мне знать, если это не охватывает все возможности принудительной сборки мусора 28.12.2020

Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..