Application turns black when dragged from a 4k monitor to a FullHD monitor

不打扰是莪最后的温柔 提交于 2019-12-11 06:45:22

问题


My notebook has a 4k display. My external monitor is 1920. When I drag my Java Swing app window from the 4k display onto the external monitor it gets completely black except for the window frame. It doesn't matter whether I maximize it on the external monitor or not.

Here is the HelloWorldSwing example I got from Oracle.com. It shows the exact same behaviour.

import javax.swing.*;        

public class HelloWorldSwing {
    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("HelloWorldSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Add the ubiquitous "Hello World" label.
        JLabel label = new JLabel("Hello World");
        frame.getContentPane().add(label);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

It looks like a bug in Swing. Anyway, I have to find a solution/work-around. Any ideas?

I'm running jdk/jre 1.8.0 121.


回答1:


Although I didn't encounter such a problem yet on any multi-screen environment I've tried so far with Swing - I might help debugging it.

Try running this code example:

public class HelloWorldSwing
{
    private static void createAndShowGUI ( final GraphicsDevice device )
    {
        final GraphicsConfiguration conf = device.getDefaultConfiguration ();

        final JFrame frame = new JFrame ( "HelloWorldSwing", conf );
        frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );

        final JLabel label = new JLabel ( "Hello World", SwingConstants.CENTER );
        frame.getContentPane ().add ( label );

        final Rectangle sb = conf.getBounds ();
        frame.setBounds ( sb.x + sb.width / 2 - 100, sb.y + sb.height / 2 - 100, 200, 200 );

        frame.setVisible ( true );
    }

    public static void main ( final String[] args )
    {
        SwingUtilities.invokeLater ( new Runnable ()
        {
            @Override
            public void run ()
            {
                final GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
                final GraphicsDevice[] devices = env.getScreenDevices ();
                for ( final GraphicsDevice device : devices )
                {
                    if ( device.getType () == GraphicsDevice.TYPE_RASTER_SCREEN )
                    {
                        createAndShowGUI ( device );
                    }
                }
            }
        } );
    }
}

This will basically place one frame on each of the screens devices available in your system. It will also provide default screen graphics configuration into each frame.

Check if you have the same problems dragging frame to your notebook screen or not and whether there are any other problems.

Edit1: Also it might be quite important to know which JDK/JRE you are using to run your code example since there were some related internal changes. If you are running some old JDK it might not be the best idea on newer Mac OS X versions.

Edit2: I would try doing a few more things to find out more:

  1. Setup Nimbus Look and Feel before displaying frames and try dragging them with that custom L&F installed.

  2. Setup system (native) look and feel as shown in the tutorial here - this might have some effect on Mac OS X.

  3. Try to run Java FX example and drag it between displays and see if you get the same problem there or not - you are already using JDK 8 so it should be easily doable. Java FX is just the new UI framework that was introduced some time ago.

And in general I could say that Swing has quite poor support for high-res displays, so even if everything runs properly and you don't get the black screen you will see other issues like the UI being blurry or low-quality text rendering.




回答2:


I found a solution. Basically I added a component listener to my main frame and listen on move events. Whenever the frame is moved I check on which display it is located. As soon as the frame has been moved to another display I set it invisible, then set new bounds located on the "new" display, set the extended state to maximized and finally make the frame visible again.

For the last minutes I wildly dragged windows from one display to another all while jumping for joy. If you also want that much fun in your life, here is the code:

mainFrame.addComponentListener(new ComponentListener()
    {
        @Override
        public void componentMoved(ComponentEvent evt)
        {
            GraphicsConfiguration conf = mainFrame.getGraphicsConfiguration();
            GraphicsDevice curDisplay = conf.getDevice();
            GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();

            GraphicsDevice[] allDisplays = env.getScreenDevices();
            for (int i = 0; i < allDisplays.length; i++)
            {
                if (allDisplays[i].equals(curDisplay))
                {
                    //the window has been dragged to another display
                    if (i != _currentDisplayIndex)
                    {
                        final Rectangle sb = conf.getBounds();

                        mainFrame.setVisible(false);
                        //it is important to set the bounds somewhere on the new display before setting the extended state to maximized
                        mainFrame.setBounds(sb.x, sb.y, 1000, 800);
                        mainFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
                        mainFrame.setVisible(true);

                        _currentDisplayIndex = i;
                    }
                }
            }

        }

        @Override
        public void componentShown(ComponentEvent evt)
        {
        }

        @Override
        public void componentResized(ComponentEvent evt)
        {
        }

        @Override
        public void componentHidden(ComponentEvent evt)
        {
        }
    });

Yippie!

Side note: I tried to take a screenshot of the black window earlier. However, the screenshot isn't black, but just normally shows all swing components. That makes me believe, that it is not only a swing issue, but also some sort of a windows/display driver issue. Pressing "printscreen" doesn't trigger anything in java (I guess), but only refreshes the display.



来源:https://stackoverflow.com/questions/42367058/application-turns-black-when-dragged-from-a-4k-monitor-to-a-fullhd-monitor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!