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

时间:2014-11-13 15:23:29

标签: java swing awt multiscreen

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

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.实际上只有1个屏幕设备 我检查GraphicsEnvironment.getLocalGraphicsEnvironment()创建一个像singleton这样的实例。这意味着无法更新?还有一件事,我不想要紧密程序并再次打开。
如何获得像这种情况的屏幕设备的正确信息?
而且我还希望Java决定哪个类(扩展GraphicsEnvironment)提供屏幕设备信息,取决于操作系统 谢谢你的进步!

1 个答案:

答案 0 :(得分:2)

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

  

免责声明:使用反射时可能会出现许多问题。你应该意识到你在这里依赖于未指明的行为。如果底层实现发生更改,则以下示例程序可能不再起作用...

     

...虽然我认为这是"不太可能",至少

以下是一个展示如何运作的示例:

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);
            }
        }
    }

}