2017-07-26 35 views
2

我正在嘗試在Mac OSX上創建一個透明的無邊界JavaFX窗口/覆蓋圖,以允許用戶通過繪製一個矩形來選擇屏幕區域,然後對該區域進行屏幕截圖。如何將JavaFX窗口配置爲在Mac OSX Dock/Menubar之上浮動?

爲了在OSX上執行此操作,我必須以某種方式將我的JavaFX窗口配置爲在Mac OSX Dock/Menubar上方浮動,因爲默認情況下窗口自動強制置於下方。通過這個,我的意思是我不能將一個窗口拖到碼頭或菜單欄上,因爲它被強制放置在它下面,因此很難實現合適的覆蓋。

如何通過Cocoa配置類似於NSWindow級別的JavaFX窗口的級別?

下面的截圖(來自一個類似電子相關後服用)突出的問題,就是我的目標是實現:

當前結果:https://i.stack.imgur.com/nmGvG.png

Intented結果:https://i.stack.imgur.com/kD6MR.png

+0

您能否提供用於生成當前結果的[mcve]代碼? – jewelsea

+0

我感覺唯一的方法就是編寫一些本地代碼[獲取HWND句柄的OS X等價物](https://stackoverflow.com/questions/38175031/is-it-somehow-可能會得到一個javawx-window-in-java-9)並且適當地操作[NSWindow級別](https://developer.apple.com/documentation/appkit/nswindow/ 1419511電平)。我不認爲你會在公共的JavaFX API中找到任何東西來直接支持這個功能。 – jewelsea

+0

有一些代碼可以在[com.sun.glass.ui.Window]中完成此操作(http://hg.openjdk.java.net/openjfx/9/rt/file/dc2bda380efe/modules/javafx.graphics/src /main/java/com/sun/glass/ui/Window.java#l186),它有一個'setLevel(Level.TOPMOST)'方法,它是「最頂層的窗口級別,可以覆蓋系統UI元素,例如dock ,任務欄等「。由於這個類在'com.sun'層次結構中是私有的,它不是公共API(所以不會被直接支持,並且在將來的Java版本中可能不起作用),我不知道如何從你的應用程序調用這個功能。 – jewelsea

回答

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塞拉利昂,我還測試了在Arch Linux的瓦特/ KDE等離子和設置的這種方法最大窗口級別不適用於該平臺。它只是將窗口設置爲'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解決方案來設置菜單欄/碼頭上方的未裝飾窗口,請分享!

+0

這種黑客總是會依賴於平臺。請小心使用com.sun。*軟件包,因爲它們可能會在沒有警告或從發佈到發佈的適當文檔的情況下更改。看上面JewelSea的評論... – Eric

相關問題