Stage.close () не работает javafx

Пропустить реквизит для направления детей.

Посмотреть все другие ответы

Пропустить общие глобальные данные через дерево компонентов через контекст

Контекст предназначен для обмена данными, которые можно считать «глобальными» для дерева компонентов React, таких как текущий аутентифицированный пользователь, тема или предпочтительный язык. 1

blockquote>

Отказ от ответственности: это обновленный ответ, предыдущий использовал старый контекстный API

Он основан на принципе Consumer / Provide , Во-первых, создайте свой контекст

const { Provider, Consumer } = React.createContext(defaultValue);

Затем используйте через


  {children} /* potential consumers */

и


  {value => /* render something based on the context value */}

Все потребители, являющиеся потомками Провайдера будет повторно отображаться всякий раз, когда изменяется значение поддержки поставщика. Распространение от Провайдера к его Потребителям-потомкам не подлежит методу shouldComponentUpdate, поэтому потребитель обновляется даже тогда, когда компонент-предок освобождается от обновления. 1

blockquote>

Полный пример, полу-псевдокод.

import React from 'react';

const { Provider, Consumer } = React.createContext({ color: 'white' });

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: { color: 'black' },
    };
  }

  render() {
    return (
      
        
      
    );
  }
}

class Toolbar extends React.Component {
  render() {
    return ( 
      

Consumer can be arbitrary levels deep

{value =>

The toolbar will be in color {value.color}

}
); } }

1 https://facebook.github.io/react/docs/context. HTML

0
задан shoover 13 July 2018 в 23:39
поделиться

1 ответ

Проблема заключается в том, что вы пытаетесь закрыть Stage из потока другого , чем JavaFX Application Thread. Посмотрев документацию по Stage, вы увидите:

Объекты сцены должны быть сконструированы и изменены в приложении JavaFX Application Thread.

Тема приложения JavaFX создается как часть процесса запуска для среды исполнения JavaFX. Дополнительную информацию см. В классе Application и методе Platform.startup (Runnable).

Тем не менее, Service при запуске выполнит свой Task на фоне . В частности, метод call() для Task выполняется на указанном фоновом потоке. Я только что протестировал попытку закрыть Stage в фоновом потоке, чтобы узнать, что произойдет (независимо от того, будет ли выбрано исключение). Результатом был java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3.

Причина, по которой вы этого не видите, - это не наблюдение за Service за сбой. Вы можете посмотреть ответ на этот вопрос , чтобы посмотреть, как смотреть на провал. Ответ конкретно говорит о Task, но такое же поведение присутствует в Service.

Что вам нужно сделать, чтобы заставить ваш код работать, чтобы убедиться, что close() вызывается в приложении JavaFX Нить. Самый простой способ сделать это - обернуть close() в вызов Platform.runLater(Runnable) .

Service<Void> cicle = new Service<Void>() {
    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {
            volatile boolean waiting = false;

            @Override
            protected Void call() throws Exception {
                Timer.start();
                while (Timer.update() / 1000 < time) {
                    System.out.println(Timer.update())
                }
                Platform.runLater(() -> close()); // wrapped in Platform#runLater
                return null;
            }
        };
    }
};

Вы также можете отменить Service.succeeded() , который всегда будет вызываться в потоке приложений JavaFX (но только в случае успеха Service). В этом случае вы удалите вызов close() из метода call().

Service<Void> cicle = new Service<Void>() {
    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {
            volatile boolean waiting = false;

            @Override
            protected Void call() throws Exception {
                Timer.start();
                while (Timer.update() / 1000 < time) {
                    System.out.println(Timer.update())
                }
                return null;
            }
        };
    }
    @Override
    protected void succeeded() {
        close();
    }

};

Существуют и другие способы: прослушивание свойства state с помощью setOnSucceeded(EventHandler) , и т.д ...

1
ответ дан Slaw 17 August 2018 в 12:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: