You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX如何移除标题栏但保留原生窗口边框?

在JavaFX中移除标题栏但保留Windows原生边框的方案

JavaFX原生的StageStyle枚举确实没有直接提供“保留系统边框但移除标题栏”的选项,不过我们可以通过调用Windows平台API实现这个需求,同时还能自定义顶部区域添加返回按钮。以下是具体实现步骤:

1. 依赖准备(JNA)

要调用Win32 API,需引入JNA库,Maven依赖如下:

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.13.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.13.0</version>
</dependency>

2. 获取窗口句柄并修改样式

通过JavaFX内部API获取Stage对应的Windows窗口句柄,再调用Win32 API移除标题栏样式:

import com.sun.glass.ui.Window;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;
import javafx.stage.Stage;

public class WindowUtils {
    public static void removeTitleBar(Stage stage) {
        // 获取JavaFX窗口的原生句柄
        Window glassWindow = stage.getPeer();
        long hwnd = glassWindow.getNativeWindow();
        
        User32 user32 = User32.INSTANCE;
        WinDef.HWND hWnd = new WinDef.HWND(new Pointer(hwnd));
        
        // 获取当前窗口样式
        long style = user32.GetWindowLongPtr(hWnd, WinUser.GWL_STYLE).longValue();
        
        // 移除标题栏样式,同时保留边框和可调整大小的属性
        long newStyle = style & ~WinUser.WS_CAPTION;
        newStyle |= WinUser.WS_BORDER | WinUser.WS_THICKFRAME;
        
        // 应用新样式并刷新窗口
        user32.SetWindowLongPtr(hWnd, WinUser.GWL_STYLE, new WinDef.LONG(newStyle));
        user32.SetWindowPos(hWnd, null, 0, 0, 0, 0, 
            WinUser.SWP_NOMOVE | WinUser.SWP_NOSIZE | WinUser.SWP_FRAMECHANGED);
    }
}

注意:com.sun.glass.ui.Window是JavaFX内部API,JavaFX 11+需添加VM参数--add-exports javafx.graphics/com.sun.glass.ui=ALL-UNNAMED才能访问。

3. 自定义顶部区域并添加返回按钮

移除标题栏后,可在Scene顶部添加自定义面板,放置返回按钮并实现窗口拖动:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class CustomTitleBarApp extends Application {
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("自定义标题栏示例");
        primaryStage.initStyle(StageStyle.DECORATED);
        
        // 自定义顶部栏
        HBox titleBar = new HBox();
        titleBar.setStyle("-fx-background-color: #f0f0f0; -fx-padding: 8px;");
        
        Button backBtn = new Button("返回");
        backBtn.setOnAction(e -> {
            // 替换为你的返回逻辑
            System.out.println("触发返回操作");
        });
        titleBar.getChildren().add(backBtn);
        
        // 主内容布局
        BorderPane root = new BorderPane();
        root.setTop(titleBar);
        root.setCenter(new Label("应用主内容区域"));
        
        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        
        // 必须在窗口显示后修改样式,确保句柄已生成
        primaryStage.show();
        WindowUtils.removeTitleBar(primaryStage);
        
        // 实现窗口拖动功能
        double[] dragDelta = new double[2];
        titleBar.setOnMousePressed(e -> {
            dragDelta[0] = primaryStage.getX() - e.getScreenX();
            dragDelta[1] = primaryStage.getY() - e.getScreenY();
        });
        titleBar.setOnMouseDragged(e -> {
            primaryStage.setX(e.getScreenX() + dragDelta[0]);
            primaryStage.setY(e.getScreenY() + dragDelta[1]);
        });
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

4. 注意事项

  • 该方案仅适用于Windows平台,跨平台需针对Linux(GTK)、macOS(Cocoa)编写对应平台代码。
  • 内部API存在版本兼容性风险,升级JavaFX时需测试验证。
  • 移除标题栏后系统默认的最小化/最大化/关闭按钮会消失,需在自定义标题栏中添加对应按钮,通过primaryStage.setIconified(true)、primaryStage.setMaximized(true)、primaryStage.close()实现功能。

内容的提问来源于stack exchange,提问作者Shiedix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 18:53:12