java 如何用Java检测当前显示?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2234476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:12:09  来源:igfitidea点击:

How to detect the current display with Java?

java

提问by Nate

I have 2 displays connected, so I can either launch my Java application on the primary or the secondary display.

我连接了 2 个显示器,因此我可以在主显示器或辅助显示器上启动我的 Java 应用程序。

The question is:How can I know which display contains my app window, i.e., is there a way to detect the current display with Java?

问题是:我怎么知道哪个显示包含我的应用程序窗口,即有没有办法用 Java 检测当前显示?

回答by Nate

java.awt.Windowis the base class of all top level windows (Frame, JFrame, Dialog, etc.) and it contains the getGraphicsConfiguration()method that returns the GraphicsConfigurationthat window is using. GraphicsConfiguration has the getGraphicsDevice()method which returns the GraphicsDevicethat the GraphicsConfiguration belongs to. You can then use the GraphicsEnvironmentclass to test this against all GraphicsDevices in the system, and see which one the Window belongs to.

java.awt.Window是所有顶级窗口(Frame、JFrame、Dialog 等)的基类,它包含getGraphicsConfiguration()返回窗口正在使用的GraphicsConfiguration的方法。GraphicsConfiguration 具有getGraphicsDevice()返回GraphicsConfiguration 所属的GraphicsDevice的方法。然后,您可以使用GraphicsEnvironment类对系统中的所有 GraphicsDevices 进行测试,并查看 Window 属于哪一个。

Window myWindow = ....
// ...
GraphicsConfiguration config = myWindow.getGraphicsConfiguration();
GraphicsDevice myScreen = config.getDevice();
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
// AFAIK - there are no guarantees that screen devices are in order... 
// but they have been on every system I've used.
GraphicsDevice[] allScreens = env.getScreenDevices();
int myScreenIndex = -1;
for (int i = 0; i < allScreens.length; i++) {
    if (allScreens[i].equals(myScreen))
    {
        myScreenIndex = i;
        break;
    }
}
System.out.println("window is on screen" + myScreenIndex);

回答by perplexed

The method proposed by Nate does not work when another monitor has just been added to the system and the user repositions the Java window into that monitor. This is a situation my users frequently face, and the only way around it for me has been to restart java.exe to force it to reenumerate the monitors.

当另一个监视器刚刚添加到系统并且用户将 Java 窗口重新定位到该监视器时,Nate 提出的方法不起作用。这是我的用户经常遇到的情况,对我来说唯一的解决方法是重新启动 java.exe 以强制它重新枚举监视器。

The main issue is myWindow.getGraphicsConfiguration().getDevice() always returns the originaldevice where the Java Applet or app was started. You would expect it to show the current monitor, but my own experience (a very time consuming and frustrating one) is that simply relying on myWindow.getGraphicsConfiguration().getDevice() is not foolproof. If someone has a different approach that's more reliable, please let me know.

主要问题是 myWindow.getGraphicsConfiguration().getDevice() 总是返回启动 Java Applet 或应用程序的原始设备。您会期望它显示当前监视器,但我自己的经验(非常耗时且令人沮丧)是,仅仅依赖 myWindow.getGraphicsConfiguration().getDevice() 并不是万无一失的。如果有人有更可靠的不同方法,请告诉我。

Performing the match for screens (using the allScreen[i].equals(myScreen) call) then continues to return the original monitor where the Applet was invoked, and not the new monitor where it might have gotten repositioned.

执行屏幕匹配(使用 allScreen[i].equals(myScreen) 调用)然后继续返回调用 Applet 的原始监视器,而不是可能已重新定位的新监视器。

回答by Wolf

Nate's solution seem to work in most, but not allcases, as I had to experience. perplexed mentions he had problems when monitors got connected, I had issues with "Win+Left" and "Win+Right" key commands. My solution to the problem looks like this (maybe the solution has problems on it's own, but at least this works better for me than Nate's solution):

Nate 的解决方案似乎适用于大多数情况,但不是所有情况,正如我所经历的那样。困惑地提到他在连接显示器时遇到了问题,我遇到了“Win+Left”和“Win+Right”键命令的问题。我对问题的解决方案看起来像这样(也许解决方案本身就有问题,但至少这比 Nate 的解决方案对我更有效):

GraphicsDevice myDevice = myFrame.getGraphicsConfiguration().getDevice();
for(GraphicsDevice gd:GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()){
    if(frame.getLocation().getX() >= gd.getDefaultConfiguration().getBounds().getMinX() &&
        frame.getLocation().getX() < gd.getDefaultConfiguration().getBounds().getMaxX() &&
        frame.getLocation().getY() >= gd.getDefaultConfiguration().getBounds().getMinY() &&
        frame.getLocation().getY() < gd.getDefaultConfiguration().getBounds().getMaxY())
        myDevice=gd;
}

回答by Alexander Zuban

This works for me

这对我有用

    public static GraphicsDevice getWindowDevice(Window window) {
    Rectangle bounds = window.getBounds();
    return asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()).stream()

            // pick devices where window located
            .filter(d -> d.getDefaultConfiguration().getBounds().intersects(bounds))

            // sort by biggest intersection square
            .sorted((f, s) -> Long.compare(//
                    square(f.getDefaultConfiguration().getBounds().intersection(bounds)),
                    square(s.getDefaultConfiguration().getBounds().intersection(bounds))))

            // use one with the biggest part of the window
            .reduce((f, s) -> s) //

            // fallback to default device
            .orElse(window.getGraphicsConfiguration().getDevice());
}

public static long square(Rectangle rec) {
    return Math.abs(rec.width * rec.height);
}