JavaFX 25 で追加された HeaderBar (プレビュー)


はじめに

最近のディスクトップアプリケーションは、ウインドウのタイトルバーにコントロールを配置するものが増えてきました。Electron 系だと一般的ですね。

例えば VS Code のタイトルバーは以下のようになっています。

JavaFX でこのようなタイトルバーを実現するには、StageStyle.UNDECORATED で装飾無しのウインドウを作成し、タイトルバーを自作するしかありませんでした。

JavaFX 25 では、プレビュー版ではありますが、タイトルバーにコントロールを配置する機能が追加されました。

bugs.openjdk.org


タイトルバーのカスタマイズ

タイトルバーをカスタマイズするには JavaFX 25 で追加された javafx.scene.layout.HeaderBar にコントロールを追加し、

var headerBar = new HeaderBar();
headerBar.setLeading(node1);
headerBar.setCenter(node2);
headerBar.setTrailing(node3);

HeaderBar を BorderPane に追加し、stage.initStyle(StageStyle.EXTENDED) を指定するだけです。

var root = new BorderPane();
root.setTop(headerBar);

Scene scene = new Scene(root);
stage.setScene(scene);
stage.initStyle(StageStyle.EXTENDED);


サンプルアプリケーション

build.gradle.kts を設定します。

org.openjfx.javafxplugin プラグインで JavaFX 25 を導入します。

plugins {
    application
    id("org.openjfx.javafxplugin") version "0.1.0"
}

repositories {
    mavenCentral()
}

dependencies {
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(25)
    }
}

application {
    mainClass = "org.example.App"
    applicationDefaultJvmArgs = listOf(
        "-Djavafx.enablePreview=true",
        "--enable-native-access=javafx.graphics",
    )
}

javafx {
    version = "25"
    modules("javafx.controls")
}

プレビュー機能を有効にするため、アプリケーションプラグインの設定で -Djavafx.enablePreview=true を指定する必要があります。

org.openjfx.javafxplugin プラグインを使う場合、現時点では gradle.properties にて configuration-cache を無効にする必要があります。

org.gradle.configuration-cache=false

アプリケーションは以下のように実装します。

package org.example;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HeaderBar;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class App extends Application {

    @Override
    public void start(Stage stage) {

        var textField = new TextField();
        textField.setPromptText("Search...");
        textField.setMaxWidth(300);
        HeaderBar.setMargin(textField, new Insets(5, 10, 5, 10));
        HeaderBar.setAlignment(textField, Pos.TOP_CENTER);

        var headerBar = new HeaderBar();
        headerBar.setCenter(textField);

        var root = new BorderPane();
        root.setTop(headerBar);
        var text = new Label("Hello, JavaFX");
        text.setFocusTraversable(true);
        root.setCenter(text);

        Scene scene = new Scene(root, 700, 300);
        stage.setScene(scene);
        stage.initStyle(StageStyle.EXTENDED);
        stage.show();
        text.requestFocus();
    }

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


サンプルアプリケーションの実行

サンプルアプリケーションを実行してみましょう。

./gradlew run

以下のようにタイトルバーにコントロールが表示されます。

Windows の場合は以下のようになります。

なお、タイトルバーは、 OS ではなくJavaFX側で描画しているため、例えばタイトルバーの色などの指定は、自身で行う必要があります(最大化・最小化・コンテキストメニューなどの挙動は JavaFX 側でよしなに処理してくれます)。