JavaFX で Lightbox 的なもの

JavaFXLightbox 的なものを出したかったんです。 Lightbox というと web でよく見るアレですね、背景暗くなって画像表示するアレ。出来上がってから Lightbox って名前を思い出したので、最初に "JavaFX Lightbox" とかで検索しとけばもっといろいろやり方あったんじゃないかと今更アレですが、まぁまがりなりにも出来たので一応まとめときます。

完成品

まずは出来上がりから。親画面のボタンを押すと・・・

こんな感じに Lightbox 的なものが出ます。

画像じゃないんかい!と言われそうですが、単にサンプル作るのがめんどくさかっただけです・・。モーダルダイアログ代わりに使うとかでもいいかもですね。

以下、実装です。

親画面コントローラー( MainWindowController )

普通に FXML とコントローラーを作って、ボタン配置してハンドラーを書きます。 このへんは NetBeans でプロジェクト作った時に自動生成されるやつをいじる感じでおk。

	@FXML
	private Pane rootPane; // FXML のルート要素

	@FXML
	private void handleButtonAction(ActionEvent event) {
		try {
			FXMLLoader loader = new FXMLLoader(getClass().getResource("Ligntbox.fxml"));
			loader.load();
			LightboxController controller = loader.getController();
			controller.showOn(rootPane);
		} catch (IOException ex) {
			// なんか適当にエラー処理でも
			Logger.getLogger(MainWindowController.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

ハンドラー内で FXMLLoader から Lightbox 画面のコントローラーを取得してごにょごにょしています。

Lightbox 画面コントローラー( LightboxController )

Lightbox 的なものを表示するコントローラーと FXML を用意します。親画面のコントローラーのハンドラーで呼ばれている処理は以下のとおりです。

	@FXML
	private Pane rootPane; // FXML のルート要素
	private Pane parent; // 親のルート要素

	@FXML
	private void handleCloseButton(ActionEvent event) {
		parent.getChildren().remove(rootPane);
	}

	void showOn(Pane parent) {
		this.parent = parent;
		// 親のルートとサイズを合わせておく
		rootPane.prefHeightProperty().bind(parent.heightProperty());
		rootPane.prefWidthProperty().bind(parent.widthProperty());

		parent.getChildren().add(rootPane);
	}

親から渡された要素に自身のルート要素を add してる感じですね。これはさくらばさんの JavaFX でプレゼンツール - JavaFX in the Box を参考にさせていただきました。親の Pane をフィールドで保持しているのは閉じるボタンを押された時にリムーブするためです。

背景の薄暗いのは css で。薄暗い AnchorPane の上に白い AnchorPane を載せています。

.lightboxBackground {
	-fx-background-color: rgba(0,0,0,0.5);
}
.ligntboxForeground {
	-fx-background-color: #ffffff;
}

とまぁこんな具合です。もっといい方法があるかもしれんけどまぁいいや・・。

画像を表示する場合

本来の Lightbox のように画像を表示する場合は ImaveView とか使えばいいと思います。しかし ImageView はウインドウをリサイズした場合の画像のリサイズがどうもうまくないです。 JavaFX ImageView resize in StackPane - Stack Overflow からリンクされてる JIRA(要ログイン)に添付されている ImageViewPane なるものを使うといい感じにできます。