0

так быстро, я делаю программу, которая демонстрирует методы, используемые для графического рисования компьютера. Мне нужно создать временную шкалу или историю таких действий, как (placeVertex (x, y), moveVertex (newX, newY) и т. Д.) И итерации (вперед и назад, автоматически или вручную)JavaFX Transition анимация ждет

Я уже достиг этого, используя команду но некоторые из этих команд используют переходы. Первой идеей было использование блокировки интерфейса Condition, ожидания и сигнала в setOnFinished между каждой командой, но это привело к зависанию gui.

Я попробовал SequentialTransition, но это бесполезно для моей проблемы - нельзя динамически изменять свойства между переходами.

Есть ли возможность как-то сообщить поколению, что один переход закончился, а затем может работать без зависания графического интерфейса и рисования?

Спасибо!

редактировать: Я буду стараться, чтобы упростить все это Вот мой Командный интерфейс и один из этих команд:

public interface Command { 
     public void execute(); 
    } 

public class MoveVertex implements Command { 
     public MoveVertex(Data d, Vertex v, double changedX, double changedY){..}; 

     @Override 
     public void execute() {   
      Path path = new Path();   
      path.getElements().add(new MoveTo(v.getCenterX(), v.getCenterY())); 
      path.getElements().add(new LineTo(changedX, changedY)); 

      PathTransition pathTransition = new PathTransition(); 
      pathTransition.setDuration(Duration.millis(velocity)); 
      pathTransition.setPath(path); 
      pathTransition.setNode(v.getVertex()); 

      pathTransition.play(); } 
    } 

Эти команды хранятся в моем классе истории, которая в основном

private List<Command> history; 

И я просматриваю список и выполняю команды

public boolean executeNext() { 
    if (history.size() != position) { 
     history.get(position).execute(); 
     position++; 
     return true; 
    } 
    return false; 
} 

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

+1

ли не [onFinsihedProperty с переходной в) (] (http://docs.oracle.com/javafx/2/api/javafx/animation/Animation.html#onFinishedProperty%28%29) Работа для вас? – ItachiUchiha

+0

@ItachiUchiha не очень, например, у меня есть один круг, два перехода пути, первый из них перемещает круг от 0 до 100 100, второй - один и тот же круг где-то в другом месте, я хочу обновить местоположение в зависимости от первого хода, но даже если i поместите новые места 'MoveTo' в' onFinishedProperty() 'его не работает, возможно потому, что переход уже создан из-за этого? – Sappo

+0

Это странно, что onFinished не работает для вас, можете ли вы включить [mcve] (http://stackoverflow.com/help/mcve) в свой вопрос, который реплицирует проблему? Использование обработчиков событий/собеседников свойств, которые обращаются к соответствующим событиям, является правильным решением, используя то, что приостанавливает или сглажает поток приложений JavaFX, является неправильным решением. – jewelsea

ответ

1

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

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

import javafx.animation.*; 
import javafx.application.Application; 
import javafx.event.*; 
import javafx.geometry.Point2D; 
import javafx.scene.*; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.*; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

import java.util.Random; 

// animates moving a node forever in a random walk pattern. 
public class RandomWalk extends Application { 

    private static final Random random = new Random(42); 

    private static final double W = 200; 
    private static final double H = 200; 
    private static final double R = 10; 

    private static final Node node = new Circle(
      R, Color.FORESTGREEN 
    ); 

    @Override 
    public void start(Stage stage) { 
     // start from the center of the screen. 
     node.relocate(W/2 - R, H/2 - R); 

     stage.setScene(new Scene(new Pane(node), W, H)); 
     stage.show(); 

     walk(); 
    } 

    // start walking from the current position to random points in sequence. 
    private void walk() { 
     final Point2D to = getRandomPoint(); 
     final Transition transition = createMovementTransition(
       node, 
       to 
     ); 

     transition.setOnFinished(
       walkFrom(to) 
     ); 
     transition.play(); 
    } 

    private EventHandler<ActionEvent> walkFrom(final Point2D from) { 
     return event -> { 
      // Finished handler might be called a frame before transition complete, 
      // leading to glitches if we relocate in the handler. 
      // The transition works by manipulating translation values, 
      // so zero the translation out before relocating the node. 
      node.setTranslateX(0); 
      node.setTranslateY(0); 

      // After the transition is complete, move the node to the new location. 
      // Relocation co-ordinates are adjusted by the circle's radius. 
      // For a standard node, the R adjustment would be unnecessary 
      // as most nodes are located at the top left corner of the node 
      // rather than at the center like a circle is. 
      node.relocate(
        from.getX() - R, 
        from.getY() - R 
      ); 

      // Generate the next random point and play a transition to walk to it. 
      // I'd rather not use recursion here as if you recurse long enough, 
      // then you will end up with a stack overflow, but I'm not quite sure 
      // how to do this without recursion. 
      final Point2D next = getRandomPoint(); 
      final Transition transition = createMovementTransition(node, next); 
      transition.setOnFinished(walkFrom(next)); 
      transition.play(); 
     }; 
    } 

    // We use a PathTransition to move from the current position to the next. 
    // For the simple straight-line movement we are doing, 
    // a straight TranslateTransition would have been fine. 
    // A PathTransition is just used to demonstrate that this 
    // can work for the generic path case, not just straight line movement. 
    private Transition createMovementTransition(Node node, Point2D to) { 
     Path path = new Path(
       new MoveTo(
         0, 
         0 
       ), 
       new LineTo(
         to.getX() - node.getLayoutX(), 
         to.getY() - node.getLayoutY() 
       ) 
     ); 

     return new PathTransition(
       Duration.seconds(2), 
       path, 
       node 
     ); 
    } 

    // @return a random location within a bounding rectangle (0, 0, W, H) 
    // with a margin of R kept between the point and the bounding rectangle edge. 
    private Point2D getRandomPoint() { 
     return new Point2D(
       random.nextInt((int) (W - 2*R)) + R, 
       random.nextInt((int) (H - 2*R)) + R 
     ); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

Спасибо за решение, к сожалению, для меня мне пришлось покинуть город в течение двух дней, поэтому я попробую его позже! Я делаю это как можно скорее, а затем дам вам знать, как это работает. Я тоже думал о рекурсии, поэтому мне интересно. Единственная проблема, которую я вижу, заключается в приостановке в середине поколений, а затем в поиске точки, где она заканчивается (иногда в длинной рекурсии), так что .. мы увидим – Sappo

Смежные вопросы