3

スタート ボタンと、マップのタイルを表すいくつかの四角形を含む Java FX シーンがあります。エクスプローラーを表す球体も描画しました (マップを探索する必要があります) が、アニメーションの実行に問題があります。

開始ボタンの OnMouseClicked ハンドラーで、球体の位置と訪問したタイルの色を変更するマップを探索するためのアルゴリズムを開始します。問題は、アルゴリズムの実行中にシーンが更新されないことです。そのため、最終的なシーンがどのように見えるか (アルゴリズムの実行が停止した後) しかわかりません。すべての色の変化を順番に確認できるように、シーンを強制的に更新するにはどうすればよいですか?

後で編集:

import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Test extends Application {

private static final double boxOuterSize = 50;
private static final double boxInnerSize = 48;
private static final double boxCornerRadius = 20;

private Stage applicationStage;
private Scene applicationScene;

private static double   sceneWidth  = 1024;
private static double   sceneHeight = 800;
private static HBox     container = new HBox();
private static Group    root = new Group();
private Rectangle[] rectangles = new Rectangle[10];

@Override
public void start(Stage mainStage) throws Exception {

    applicationStage = mainStage;
    container.setSpacing(10);
    container.setPadding(new Insets(10, 10, 10, 10));

    try {
        applicationScene = new Scene(container, sceneWidth, sceneHeight);
        applicationScene.addEventHandler(EventType.ROOT,(EventHandler<? super Event>)this);
        applicationScene.setFill(Color.WHITE);

    } catch (Exception exception) {
        System.out.println ("exception : "+exception.getMessage());
    }

    applicationStage.setTitle("HurtLockerRobot - Tema 3 IA");
    applicationStage.getIcons().add(new Image("icon.png"));
    applicationStage.setScene(applicationScene);

    for(int i=0; i<10; i++) {
        Rectangle r = new Rectangle();
        r.setFill(Color.BLUE);
        r.setX(i * boxOuterSize);
        r.setY(0);
        r.setWidth(boxInnerSize);
        r.setHeight(boxInnerSize);
        r.setArcHeight(boxCornerRadius);
        r.setArcWidth(boxCornerRadius);
        r.setSmooth(true);
        rectangles[i] = r;
        root.getChildren().add(rectangles[i]);
    }

    container.getChildren().add(root);
    Button startButton = new Button("Start");
    startButton.setOnMouseClicked(new EventHandler<Event>() {
        @Override
        public void handle(Event arg0) {
            for(int i=0; i<10; i++) {
                rectangles[i].setFill(Color.RED);
                // TODO: some kind of scene refresh here
            }
        }
    });
    container.getChildren().add(startButton);

    applicationStage.show();
}

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

最初はすべての長方形が青色です。ここで取得したい動作は、四角形の色が順番に変化することです。問題は、最終結果しか表示されないことです (すべての長方形の色が同時に変わります)。

4

2 に答える 2

5

これは古い質問であり、JavaFX を初めて使用する人が直面する非常に一般的な問題であるため、私の目に留まりました。

OP が直面している問題は、待たずにすべての長方形を一度に更新するためです。

OPは、新しいスレッドを作成するか、ループの反復ごとに推定秒の間スレッドをスリープ状態にしてから、を使用してJavaFXアプリケーションスレッドの長方形の色を更新することで待機できますPlatform.runLater

@Override
public void handle(Event arg0) {
  new Thread(() -> {
     for(int i=0; i<10; i++) {
       try {
          Thread.sleep(1000); // Wait for 1 sec before updating the color
       } catch (InterruptedException e) {
          e.printStackTrace();
       }
       int finalI = i;
       Platform.runLater(() -> rectangles[finalI].setFill(Color.RED));// Update on JavaFX Application Thread
   }
}).start();

上記のスニペットは、より伝統的なやり方です。「JavaFX」の方法を使用したい場合は、Animation.

x-seconds以下は、長方形の色を変更する前に待機するコード スニペットです。PauseTransition待機は四角形ごとに適用されることで処理されるため、追加のスレッドは必要ありません。

startButton.setOnMouseClicked(new EventHandler<Event>() {
    @Override
    public void handle(Event arg0) {
        for(int i=0; i<10; i++) {
            PauseTransition pauseTransition = new PauseTransition(Duration.seconds(i));
            int finalI = i;
            pauseTransition.setOnFinished(event -> rectangles[finalI].setFill(Color.RED));
            pauseTransition.play();
        }
    }
});

長方形ごとに PauseTransition を作成し、配列内のインデックスに応じてrectangles、色を更新する前に同じ秒数待機します。

于 2016-08-16T08:58:56.830 に答える
0

これは次の理由によるものです:

exception : Test cannot be cast to javafx.event.EventHandler

さて、クラスキャスト例外がどのように発生したのかわかりません。

それ以外の場合は、遅延させるためにを使用できますThread.sleep()

アップデート:

AnimationTimerを使用してアニメーションを作成するのは良いことです。何も更新する必要はありません。

ここでは、を使用してカラーレクを表示するために短いEGを実行しましたFillTransition

コード:

import javafx.animation.FillTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;


public class NewFXMain1 extends Application {
private static final double boxOuterSize = 50;
private static final double boxInnerSize = 48;
private static final double boxCornerRadius = 20;
private Rectangle rectangles = new Rectangle();

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

@Override
public void start(Stage primaryStage) {
    primaryStage.setTitle("rect");


    Button btn = new Button();
    StackPane root = new StackPane();


    Rectangle r = new Rectangle();
    r.setFill(Color.BLUE);
    r.setX(2 * boxOuterSize);
    r.setY(0);
    r.setWidth(boxInnerSize);
    r.setHeight(boxInnerSize);
    r.setArcHeight(boxCornerRadius);
    r.setArcWidth(boxCornerRadius);
    r.setSmooth(true);
    r.localToScene(boxOuterSize, boxOuterSize);
    rectangles = r;

    root.getChildren().add(rectangles);

    btn.setText("display");
    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
           FillTransition ft = new FillTransition(Duration.millis(3000), rectangles, Color.RED, Color.BLUE);
           ft.setCycleCount(4);
           ft.setAutoReverse(true);
           ft.play();
        }
    });

    root.getChildren().add(btn);
    primaryStage.setScene(new Scene(root, 300, 250));
    primaryStage.show();
  }
}
于 2013-01-20T13:40:05.153 に答える