How to change the color of Title Bar in framework "JAVAFX“?
Asked Answered
C

3

11

I'm a beginner of JavaFX. Is there anyway to change the color of title bar. I just want to make the application all black. I have searched the JavaFX API, but I can't find any method to make it.

enter image description here

Cupellation answered 3/3, 2017 at 16:21 Comment(1)
See the following links which are for JFrame and Compose Multiplatform repectively: - github.com/kalibetre/CustomDecoratedJFrame - github.com/JetBrains/compose-multiplatform/issues/…Mirador
A
13

This is pretty much an OS dependent thing. The operating system gets to decide how titlebars and borders are displayed by default. However, it definitely can be done, if you are willing to venture into making your own title bar.

To start out, you will need to modify the application window's stage to StageStyle.UNDECORATED. Then you will need to set up your own borders and title bar (complete with things like the title, minimize button, close button, etc.). You can then add the border pane as a scene into your application's stage, and that should render your custom titlebar then without the default Windows styling.

You can find an example implementation of that here: https://mcmap.net/q/482660/-javafx-primarystage-remove-windows-borders-duplicate

Do note that because you are implementing your own titlebar, you will also lose the OS's default window drag behavior, so you will need to implement your own window-drag/window-move code. This answer might be able to help you with that: https://mcmap.net/q/502052/-moving-an-undecorated-stage-in-javafx-2

Argon answered 3/3, 2017 at 16:40 Comment(3)
setting stage to undecorated removes window 10 support for quick edge resizingYammer
is there a simple way to hack this in JNA.platform.win32? If all I want is SetSysColors?Parsimonious
I doubt that it's only an OS dependent thing. Otherwise the title bar would be dark in my case, since I've set my OS theme to dark and the title bars of all other apps look dark.Remorseless
R
1

There is a Windows API allowing you to set the color of the window title bar: DwmSetWindowAttribute and how it can be used.

With JNA you can access this API like this:

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import javafx.stage.Stage;
import javafx.stage.Window;
import lombok.val;

public class FXWinUtil {

    public static WinDef.HWND getNativeHandleForStage(Stage stage) {
        try {
            val getPeer = Window.class.getDeclaredMethod("getPeer", null);
            getPeer.setAccessible(true);
            val tkStage = getPeer.invoke(stage);
            val getRawHandle = tkStage.getClass().getMethod("getRawHandle");
            getRawHandle.setAccessible(true);
            val pointer = new Pointer((Long) getRawHandle.invoke(tkStage));
            return new WinDef.HWND(pointer);
        } catch (Exception ex) {
            System.err.println("Unable to determine native handle for window");
            return null;
        }
    }

    public static void setDarkMode(Stage stage, boolean darkMode) {
        val hwnd = FXWinUtil.getNativeHandleForStage(stage);
        val dwmapi = Dwmapi.INSTANCE;
        WinDef.BOOLByReference darkModeRef = new WinDef.BOOLByReference(new WinDef.BOOL(darkMode));

        dwmapi.DwmSetWindowAttribute(hwnd, 20, darkModeRef, Native.getNativeSize(WinDef.BOOLByReference.class));

        forceRedrawOfWindowTitleBar(stage);
    }

    private static void forceRedrawOfWindowTitleBar(Stage stage) {
        val maximized = stage.isMaximized();
        stage.setMaximized(!maximized);
        stage.setMaximized(maximized);
    }

}

Dwmapi.java:

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.PointerType;
import com.sun.jna.platform.win32.WinDef;

public interface Dwmapi extends Library {

    Dwmapi INSTANCE = Native.load("dwmapi", Dwmapi.class);

    int DwmSetWindowAttribute(WinDef.HWND hwnd, int dwAttribute, PointerType pvAttribute, int cbAttribute);

}

The code allows you to activate the dark mode of the window title bar via:

FXWinUtil.setDarkMode(stage, true);
Remorseless answered 23/6, 2023 at 20:12 Comment(2)
This is a nice example of how this can be achieved on Windows. However, it would have been nice if you had also included the Dwmapi source :)Carmarthenshire
@grill2010: Thanks for the hint. I just added the class to my post.Remorseless
B
0

Note that Native.getNativeSize(WinDef.BOOLByReference.class) in the sample code is somewhat incorrect. It should be BOOL.SIZE. The example above happens to work because Native.getNativeSize(WinDef.BOOLByReference.class) and BOOL.SIZE happens to be the same. This is not the case when passing a DWORD value:

DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, new BOOLByReference(new BOOL(enabled)), BOOL.SIZE);
DwmSetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, new DWORDByReference(new DWORD(color)), DWORD.SIZE);
Barrows answered 23/6 at 3:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.