Java GraphicalEnvironment在关闭第二个屏幕后不会更新屏幕设备

Java GraphicalEnvironment在关闭第二个屏幕后不会更新屏幕设备,java,swing,awt,multiscreen,Java,Swing,Awt,Multiscreen,我有两台显示器 我编写了非常小的Swing Java代码来收集所有屏幕设备的信息,通过在控制面板中设置display,将改变显示模式与一个或两个显示屏幕结合起来。 代码如下: import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.

我有两台显示器
我编写了非常小的Swing Java代码来收集所有屏幕设备的信息,通过在控制面板中设置display,将改变显示模式与一个或两个显示屏幕结合起来。 代码如下:

import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;


public class Main {

    public static void main(String[] args) {
        final JFrame frame = new JFrame("Demo get info screen devices");
        JButton button = new JButton("Print info screen devices");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                printInfoAllScreenDevices();
            }
        });
        frame.add(button);
        frame.setSize(500, 300);
        frame.setVisible(true);
    }
    private static void printInfoAllScreenDevices() {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice[] graphicsDevices = ge.getScreenDevices();
        System.out.println("Number of screen devices:" + graphicsDevices.length);
    }
} 
首先,我用两个屏幕启动程序,然后单击按钮(“打印信息屏幕设备”)。在输出显示中

Number of screen devices:2

接下来,我切换到一种显示模式。最后,再次单击按钮,结果仍然为2。实际上只有一个屏幕设备。
我检查GraphicsEnvironment.getLocalGraphicsEnvironment()是否创建了类似singleton的实例。这意味着不能更新?还有一件事,我不想关闭程序并再次打开。
如何获得像这种情况下的屏幕设备的正确信息?
我还想让Java根据操作系统来决定哪个类(extend GraphicsEnvironment)提供屏幕设备的信息。

谢谢你的进步

这可能很棘手。但是,快速查看源代码,您可能会尝试一些反射

免责声明:使用反射时可能会出现很多问题。您应该意识到,您依赖的是未指定的行为。如果底层实现发生更改,则以下示例程序可能不再工作

……虽然我认为这是“不可能的”,至少

下面是一个示例,说明了这可能的工作原理:

import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class GraphicsEnvironmentTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("Demo get info screen devices");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton button = new JButton("Print info screen devices");
        button.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                printInfoAllScreenDevices();
            }
        });
        frame.add(button);
        frame.setSize(500, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static void printInfoAllScreenDevices() 
    {
        GraphicsDevice graphicsDevices[] = getGraphicsDevices();
        System.out.println("Found "+graphicsDevices.length+" devices:");
        for (int i=0; i<graphicsDevices.length; i++)
        {
            System.out.println(graphicsDevices[i]);
        }
    }

    /**
     * Queries the local graphics environment for the available graphics
     * devices. This uses reflection internally. If anything goes wrong
     * with the reflective call, a RuntimeException will be thrown.
     * 
     * @return The available graphics devices.
     * @throws RuntimeException If the reflective calls fail
     */
    private static GraphicsDevice[] getGraphicsDevices() 
    {
        GraphicsEnvironment graphicsEnvironment = 
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        Class<?> c = graphicsEnvironment.getClass();
        Method getNumScreensMethod = null;
        boolean getNumScreensMethodWasAccessible = false; 
        Method makeScreenDeviceMethod = null;
        boolean makeScreenDeviceMethodWasAccessible = false;
        try
        {
            getNumScreensMethod = 
                c.getDeclaredMethod("getNumScreens");
            getNumScreensMethodWasAccessible =
                getNumScreensMethod.isAccessible();
            getNumScreensMethod.setAccessible(true);

            makeScreenDeviceMethod = 
                c.getDeclaredMethod("makeScreenDevice", int.class);
            makeScreenDeviceMethodWasAccessible =
                makeScreenDeviceMethod.isAccessible();
            makeScreenDeviceMethod.setAccessible(true);

            int numScreens = 
                (Integer) getNumScreensMethod.invoke(graphicsEnvironment);
            GraphicsDevice graphicsDevices[] = new GraphicsDevice[numScreens];
            for (int i = 0; i < numScreens; i++)
            {
                Object object = 
                    makeScreenDeviceMethod.invoke(graphicsEnvironment, i);
                graphicsDevices[i] = (GraphicsDevice) object;
            }
            return graphicsDevices;
        }
        catch (NoSuchMethodException e)
        {
            throw new RuntimeException(e);
        }
        catch (SecurityException e)
        {
            throw new RuntimeException(e);
        }
        catch (IllegalAccessException e)
        {
            throw new RuntimeException(e);
        }
        catch (IllegalArgumentException e)
        {
            throw new RuntimeException(e);
        }
        catch (InvocationTargetException e)
        {
            throw new RuntimeException(e);
        }
        finally
        {
            if (getNumScreensMethod != null)
            {
                getNumScreensMethod.setAccessible(
                    getNumScreensMethodWasAccessible);
            }
            if (makeScreenDeviceMethod != null)
            {
                makeScreenDeviceMethod.setAccessible(
                    makeScreenDeviceMethodWasAccessible);
            }
        }
    }

}
导入java.awt.GraphicsDevice;
导入java.awt.GraphicsEnvironment;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.lang.reflect.InvocationTargetException;
导入java.lang.reflect.Method;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.SwingUtilities;
公共类GraphicsEnvironmentTest
{
公共静态void main(字符串[]args)
{
SwingUtilities.invokeLater(新的Runnable()
{
@凌驾
公开募捐
{
createAndShowGUI();
}
});
}
私有静态void createAndShowGUI()
{
JFrame=newjframe(“演示获取信息屏幕设备”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton按钮=新JButton(“打印信息屏幕设备”);
addActionListener(新建ActionListener())
{
@凌驾
已执行的公共无效操作(操作事件e)
{
printInfoAllScreenDevices();
}
});
框架。添加(按钮);
框架。设置尺寸(500300);
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
私有静态void printInfoAllScreenDevices()
{
graphicsDevices graphicsDevices[]=getGraphicsDevices();
System.out.println(“找到的”+图形设备.长度+”设备:);
for(inti=0;它是