java - 关闭第二个屏幕后,图形环境不会更新屏幕设备

标签 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() 是否创建一个类似单例的实例。意思是不能更新?还有一件事,我不想关闭程序并再次打开。
像这种情况如何才能获得正确的屏幕设备信息?
我还希望Java将决定哪个类(扩展GraphicsEnvironment)提供屏幕设备的信息,取决于操作系统。
感谢您的提前!

最佳答案

这可能很棘手。但快速浏览一下源代码,您可能会尝试一些反射。

Disclaimer: Many things can go wrong when using reflection. You should be aware of the fact that you are relying on unspecified behavior here. If the underlying implementation changes, then the following example program might no longer work...

...although I consider this as "unlikely", at least

以下示例展示了其工作原理:

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 - 关闭第二个屏幕后,图形环境不会更新屏幕设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26912360/

相关文章:

Java GUI - 删除所有组件并重绘

java - 如何重新启动 Java 小程序?

java - 错误 : extra data after last expected column When trying to inserting csv file

java - 使用面板类中的按钮调用框架类中的ActionListener

java - 解析 XML 并替换来自不同数据源的值

Java Swing - 按钮不会显示,直到光标悬停在它上面

java - 如何对所有 Controller 实现 ResponseBodyAdvice?

java - 单击复选框时使用 JTable 的内容更新数据库

Java JOGL : How can create an image using both GL and Graphics?

Java AWT fillOval() 不起作用