如何配置JavaFX窗口以浮动在Mac OSX Dock /菜单栏上方?

时间:2017-07-26 19:24:46

标签: java macos javafx overlay

我正在尝试在Mac OSX上创建一个透明的无边框JavaFX窗口/覆盖图,以允许用户通过绘制矩形然后截取该区域来选择屏幕区域。

为了在OSX上执行此操作,我必须以某种方式将我的JavaFX窗口配置为浮动在Mac OSX Dock /菜单栏上方,因为默认情况下窗口会自动强制在两者下面。通过这个,我的意思是我不能将一个窗口拖到停靠栏或菜单栏上,因为它被迫在它下面,使得一个合适的叠加非常难以实现。

如何通过Cocoa配置类似于NSWindow级别的JavaFX窗口级别?

下面的截图(取自类似的与电子相关的帖子)突出了这个问题以及我的目标:

当前结果:https://i.stack.imgur.com/nmGvG.png

意图结果:https://i.stack.imgur.com/kD6MR.png

1 个答案:

答案 0 :(得分:0)

感谢jewelsea的建议,我决定使用com.sun.glass.ui.Window将基本JavaFX窗口级别设置为Mac OSX允许的最大级别。下面的代码片段显示了使用com.sun.glass.ui.Window覆盖给定窗口句柄/对象的窗口级别是多么容易,可以使用com.glass.ui.Window.getWindows()找到它。我发现了如何使用glass.ui.Window,感谢另一个StackOverflow页面中的this answer

然而,有一个小缺点(但对我个人来说不是问题):即使在设置了最大窗口水平之后,装饰的窗户也不能放在菜单栏上方,但是,它们仍然可以放在码头上方。如果你想在菜单栏上方设置一个窗口,你必须首先将它设置为Undecorated,显示它,使用com.sun.glass.ui.getWindows()。get(window_index)抓取窗口,然后将窗口级别设置为3 (最大值)。您可以在此之前或之后设置窗口的X和Y坐标,它似乎可以双向工作。

OSX解决方案代码:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class ontopTest extends Application{

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

    @Override
    public void start(final Stage stage){
        Scene scene = new Scene(new Pane(new Label("test application")));
        stage.setTitle("Override OSX Menubar test");
        // Decorated window results in our window being placed below menubar even after setting window level to max.
        stage.initStyle(StageStyle.UNDECORATED);
        // An undecorated window fixes this and can be placed above the menubar.
        stage.setWidth(300);
        stage.setHeight(300);
        stage.setScene(scene);
        // stage.setAlwaysOnTop uneeded as com.sun.glass.ui sets window to top
        stage.setY(0); // Set Y Axis to 0
        // Need to show window first
        stage.show();
        // Print all windows running in current process
        System.out.println(com.sun.glass.ui.Window.getWindows());
        // Select which window to set level (window at index 0 in this case)
        com.sun.glass.ui.Window.getWindows().get(0).setLevel(3);
        // Set window level to 3 (Maximum)
    }
}

编辑:虽然我可以确认这适用于Mac OSX Sierra,但我也在使用KDE Plasma的Arch Linux上进行了测试,这种设置最大窗口级别的方法对该平台不起作用。它只是将窗口设置为' AlwaysOnTop'模式但仍将强制在KDE / X11菜单栏下面。我所知道的(到目前为止)关于如何在Linux系统上绕过X11菜单栏的唯一解决方案是通过输入以下命令来使用wmctrl commandline X Window manager

通过窗口标题选择窗口,将窗口添加到最顶层。这也将窗口设置为AlwaysOnTop

wmctrl -r "Window Title" -b add,above

将窗口(装饰或未装饰)定位到您想要的(以前受限制的)区域,例如菜单栏,码头等上方。

wmctrl -r "Window Title" -e 0,x,y,width,height

如果您有一个基于Java的X11解决方案,可以在菜单栏/码头上方设置未修饰的窗口,请分享!