Сделать новую анимацию невозможной, когда анимация работает (отключите setOnMouseClicked во время анимации) - PullRequest
0 голосов
/ 05 сентября 2018

Я искал способ сделать это, но мне кажется, что я не могу найти решение для javafx (я нахожу его только в jQuery и javascript). У меня есть игра, где вы можете вращать плитки (ImageViews) на Mouseclick, и я делаю это с

setOnMouseClicked(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            update();
        }
    };

И обновление имеет это:

public void update() {
    Animation animation = new RotateTransition(Duration.millis(100), this);
    animation.setByAngle(90);
    animation.play();
    tile.rotate();
}

Проблема в том, что когда я слишком быстро нажимаю на плитку (пока она все еще вращается), она облажается и застревает, например, на 60 градусов. Я просто хочу сделать это так, чтобы невозможно было щелкнуть изображение в процессе анимации. Пожалуйста, помогите мне. Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Другой вариант, вместо создания отдельной переменной boolean, заключается в использовании свойства status из Animation. Вы также можете использовать один и тот же Animation для каждой плитки.

import javafx.animation.Animation.Status;
import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {

  private RotateTransition transition;

  @Override
  public void start(Stage primaryStage) throws Exception {
    GridPane root = new GridPane();
    root.setPadding(new Insets(20));
    root.setHgap(15);
    root.setVgap(15);

    EventHandler<MouseEvent> onClick = this::handleClick;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        Rectangle rect = new Rectangle(50, 50);
        rect.setOnMouseClicked(onClick);
        root.add(rect, i, j);
      }
    }

    Scene scene = new Scene(root);
    primaryStage.setScene(scene);
    primaryStage.setTitle("Animation Example");
    primaryStage.setResizable(false);
    primaryStage.show();
  }

  private void handleClick(MouseEvent event) {
    if (transition == null) {
      transition = new RotateTransition(Duration.seconds(100));
      transition.setByAngle(90);
    } else if (transition.getStatus() == Status.RUNNING) {
      return;
    }

    transition.setNode((Rectangle) event.getSource());
    transition.playFromStart();
    event.consume();
  }

}

Этот код начнет новый переход, только если он в данный момент не запущен. Однако обратите внимание, что эта установка позволяет вращать только одну плитку в любой момент времени. Если вы хотите иметь анимацию на плитку, это требует небольшой корректировки.

import java.util.HashMap;
import java.util.Map;
import javafx.animation.Animation.Status;
import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {

  private final Map<Rectangle, RotateTransition> animations = new HashMap<>();

  @Override
  public void start(Stage primaryStage) throws Exception {
    GridPane root = new GridPane();
    root.setPadding(new Insets(20));
    root.setHgap(15);
    root.setVgap(15);

    EventHandler<MouseEvent> onClick = this::handleClick;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        Rectangle rect = new Rectangle(50, 50);
        rect.setOnMouseClicked(onClick);
        root.add(rect, i, j);
      }
    }

    Scene scene = new Scene(root);
    primaryStage.setScene(scene);
    primaryStage.setTitle("Animation Example");
    primaryStage.setResizable(false);
    primaryStage.show();
  }

  private void handleClick(MouseEvent event) {
    RotateTransition animation = animations.computeIfAbsent((Rectangle) event.getSource(), rect -> {
      RotateTransition rt = new RotateTransition(Duration.millis(100), rect);
      rt.setByAngle(90);
      return rt;
    });

    if (animation.getStatus() != Status.RUNNING) {
      animation.playFromStart();
      event.consume();
    }
  }

}

Теперь у каждой плитки есть свой RotateTransition, но анимация будет воспроизводиться только в том случае, если она еще не запущена.

0 голосов
/ 05 сентября 2018

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

boolean currentlyPlaying = false;
node.setOnMouseClicked(event -> {
    if (!currentlyPlaying)
        update();
});
public void update() {
    Animation animation = new RotateTransition(Duration.millis(100), this);
    animation.setByAngle(90);
    animation.play();
    currentlyPlaying = true;
    animation.setOnFinished(event -> currentlyPlaying = false;);
    tile.rotate();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...