JavaFX: перемещение круга с потоками - PullRequest
0 голосов
/ 01 июня 2019

Я пытаюсь создать анимацию, но без использования встроенных функций, таких как TranslateTransition. На Anchor Pane я создал круг, и я хочу, чтобы он постоянно двигался вдоль некоторой линии, подобной этой:

 public void initialize()  {  
        MyThread task = new MyThread();
        new Thread(task).start();  
    }
class MyThread extends Task<Integer>
{
    @FXML
    Circle myCircle;
    @Override
    protected Integer call() throws Exception
    {
        int i= 737; //starting position
        while(true)
        {
            ((Node) myCircle).setLayoutX(i);
            i--;
            if(i%109==0) //ending position
                i=737;

        }
    }

}

Но это не движется вообще. Я новичок в потоках в javaFX, поэтому я не знаю, что я делаю неправильно. Но когда я просто напечатал несколько цифр, это сработало просто:

class MyThread extends Task<Integer>
{
    @Override
    protected Integer call() throws Exception
    {
        for(int i=0; i<10;i++)
        {
            count(i);
            count10(i);
        }

    protected void count(int i)
    {
        System.out.println(i);
    }

    protected void count10(int i)
    {
        System.out.println(10*i);
    }

}

1 Ответ

2 голосов
/ 01 июня 2019

Узлы JavaFX следует изменять только из потока приложения JavaFX.Вы изменяете свойство layoutX из фонового потока, что приводит к ненадежным результатам.

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

class MyThread extends Task<Integer> {

    @Override
    protected Integer call() throws Exception {
        final int minX = (737 / 109) * 109; // use rounding of integer division to find greatest int <= 737 divisible by 109

        while(true) {
            for (int i = 737; i >= minX; i--) {
                updateValue(i);
            }
        }
    }

}
MyThread task = new MyThread();
task.valueProperty().addListener((o, oldValue, newValue) -> circle.setLayoutX(newValue.doubleValue()));
new Thread(task).start();

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


В противном случае вам придется использовать Platform.runLater для обновления графического интерфейса, но это довольно сложно с вашим кодом, так как вы делаете обновления с достаточно высокой частотой, чтобы JavaFX не смог справиться со всемиRunnable s отправлено.

Я рекомендую использовать класс JavaFX, такой как AnimationTimer.Эти виды классов предоставляются для использования.Попытка реализовать что-то подобное самостоятельно, скорее всего, принесет больше хлопот, чем того стоит, особенно как неопытный программист.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...