山傘のプログラミング勉強日記

プログラミングに関する日記とどうでもよい雑記からなるブログです。

JavaFX 同じ画像を表示する

JavaFXでImageを複製し表示する

JavaFXで同じ画像を複数表示したいときのやり方を書きます。

親ノードと子ノードの関係?

JavaFXでは、ひとつの画像(ノード)はひとつのパネル(親ノード)にしか属することが出来ないと思います。例えば、

	ImageView imgView;

	FlowPanel fp1 = new FlowPanel();
	FlowPanel fp2 = new FlowPanel();
	
	fp1.getChildren().add(imgView);
	fp2.getChildren().add(imgView);

	Scene scene = new Scene(fp1);
	stage.setScene(scene);
	stage.show();

のように記述すると、画像は表示されません。これは、imgViewがfp2に移ったためです。Sceneの引数をfp2にすれば、画像が表示されるようになりますが、このような書き方は好ましくないと考えられます。
また、次に同じ画像を二枚表示したいときに、次のように書くとエラーが返されます。

fp.getChildren().add(imgView);
fp.getChildren().add(imgView);

これは、同じ子ノードを同じ親ノードに追加しようとしているためです。
したがって、画像を複製するには、newで新しくノードを作り直さなければなりません。
f:id:yamakasa3:20180310211112p:plain

サンプルコード

import java.nio.file.Path;
import java.nio.file.Paths;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class Test3 extends Application{
	@Override
	public void start(Stage stage) throws Exception{
		stage.setWidth(300);
		stage.setHeight(300);

		FlowPane fp = new FlowPane();

		// 画像のパスを取得してリサイズする
		Path imgPath = Paths.get("java-duke-logo.png");
		Image img = new Image(imgPath.toUri().toString());
		WritableImage reImg = new WritableImage(img.getPixelReader(), 0, 0, (int)img.getWidth(), (int)img.getHeight());

		for(int i = 0; i < 3; i++) {
			ImageView dummyImageView = new ImageView(reImg);
			dummyImageView.setFitHeight(100);
			dummyImageView.setFitWidth(100);
			fp.getChildren().add(dummyImageView);
		}
		Scene scene = new Scene(fp);
	    	stage.setScene(scene);
	    	stage.show();
	}
	public static void main(String[] args) {
        launch(args);
    }
}