JavaFX で新しいウィンドウを開く
ここでは JavaFX アプリケーションで新しいウィンドウを開く方法と、新しいウィンドウ側でウィンドウを閉じる動作を行う方法について説明します。
ここで作るサンプルプログラムの動作は次の通りです。
プログラムを起動すると、ボタン一つのウィンドウが起動します。
OK ボタンを押すと新しいウィンドウが表示します。
Close ボタンを押すとウィンドウが閉じて、元の画面に戻ります。
とても基本的なことなので、これができないとヤバいですね。
ポイントは新しいウィンドウを Stage として用意する所でしょう。
元の画面のコントローラのコード MainViewController.java は次の通りです。
package application;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MainViewController {
@FXML
void onOKAction(ActionEvent event) {
try {
showSecondWindow();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
void showSecondWindow() throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("SecondView.fxml"));
BorderPane root = (BorderPane) loader.load();
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setScene(scene);
stage.showAndWait();
}
}
ここでは自前の showSecondWindow メソッドで、二個目のウィンドウを作成して開いています。
FXML ローダーの load メソッドで Pane を作成し、それを新しい Scene に設定。 そして、それを元に Stage を作成して、showAndWait メソッドを呼び出して、ウィンドウが閉じるまで待ちます。
ちなみに、この一個目のウィンドウの FXML は次の通りです。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/8.0.171"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="application.MainViewController">
<children>
<Button mnemonicParsing="false" onAction="#onOKAction"
text="OK">
<VBox.margin>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</VBox.margin>
</Button>
</children>
</VBox>
二個目のウィンドウの FXML は次の通り。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<BorderPane xmlns="http://javafx.com/javafx/8.0.171"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="application.SecondViewController">
<center>
<VBox prefHeight="99.0" prefWidth="300.0"
BorderPane.alignment="CENTER">
<children>
<Label text="Hello!">
<font>
<Font size="24.0" />
</font>
<VBox.margin>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</VBox.margin>
</Label>
<HBox alignment="CENTER_RIGHT" prefHeight="41.0"
prefWidth="300.0">
<children>
<Button mnemonicParsing="false" onAction="#onCloseAction"
text="Close">
<HBox.margin>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</children>
</VBox>
</center>
</BorderPane>
新しく開いた二個目のウィンドウのコントローラコードは次の通り。
package application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.stage.Window;
public class SecondViewController {
@FXML
void onCloseAction(ActionEvent event) {
Scene scene = ((Node) event.getSource()).getScene();
Window window = scene.getWindow();
window.hide();
}
}
ボタンのイベントハンドラで、引数として渡される ActionEvent から Scene を取得しています。
Scene からは、getWindow メソッドによって、それが設定されている Window オブジェクトが直ちに取得できます。
これで取得できた Window オブジェクトの hide メソッドを呼ぶことで、ウィンドウを閉じることができます。
ちなみに、ここで取得できる Window オブジェクトは実際には Stage オブジェクトでもあるので、Window から Stage にキャストして、それの close メソッドを呼ぶことでもウィンドウを閉じることは可能です。(Stage は Window から派生しています)
しかしながら、JDK のドキュメントに Stage の close と Window の hide は同一であると明記されているので、わざわざダウンキャストまでして close を呼び出すこともないでしょう。
以上、JavaFX で新しいウィンドウを作成して開き、それを閉じる方法について説明しました。