JavaFX で Lightbox 的なものを出したかったんです。 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
なるものを使うといい感じにできます。