2

I try to layout three JPanels in a way that the left panel takes up about 66% of the width, and two other panels share the other 33%.
In order to properly calculate the layout, I ran into this interesting behaviour where the screen size is correctly determined as 4K resolution.
However, the ComponentEvent reports only 2575x1415, although the JFrame opens in full screen as set via extended state. Minimizing/Maximizing the JFRame makes it go to min size and to full screen size, but the reported size stays the same.
Why is that?

17:51:25.450 [main] INFO  net.ck.game.ui.TestFrame - screen width height 3840 2160
17:51:25.615 [AWT-EventQueue-0] ERROR net.ck.game.ui.TestFrame - java.awt.Rectangle[x=-7,y=-7,width=2575,height=1415]

My Example code:

import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class TestFrame extends JFrame
{
    static final long serialVersionUID = 1L;
    private static final Logger logger = (Logger) LogManager.getLogger(TestFrame.class);

    public static void main(String[] args)
    {
        JFrame frame;
        /**
         * https://stackoverflow.com/questions/11497910/java-setfullscreenwindow-keep-on-top/11499100#11499100
         */
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice[] gs = ge.getScreenDevices();

        for (int i = 0; i < gs.length; i++)
        {
            DisplayMode dm = gs[i].getDisplayMode();
            int screenWidth = dm.getWidth();
            int screenHeight = dm.getHeight();
            logger.info("screen width height {} {}", screenWidth, screenHeight);
        }

        frame = new JFrame();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setMinimumSize(new Dimension(900, 840));
        frame.setVisible(true);
        frame.toFront();

        /**
         * thanks to stackoverflow:
         * https://stackoverflow.com/questions/2781939/setting-minimum-size-limit-for-a-window-in-java-swing
         * https://stackoverflow.com/questions/8333187/how-to-check-current-window-size-in-java-swing
         */
        frame.addComponentListener(new ComponentAdapter()
        {
            /**
             * changing the component resize event to not have the UI smaller thank the
             * minimum to show the three panels next stop, wondering how they can be
             * enlarged accordingly
             */
            public void componentResized(ComponentEvent ev)
            {
                logger.error(ev.getComponent().getBounds().toString());
                Dimension d = frame.getSize();
                Dimension minD = frame.getMinimumSize();
                if (d.width < minD.width)
                    d.width = minD.width;
                if (d.height < minD.height)
                    d.height = minD.height;
                frame.setSize(d);
            }
        });
    }
}
Snorik
  • 201
  • 3
  • 15
  • 1
    I don't use a 4k screen so I can't test. Only suggestion I have is to make sure the GUI code is executed on the EDT by wrapping your code in a `SwingUtilities.invokeLater()`. – camickr Jul 11 '20 at 17:56
  • 1
    The CompnentEvent reports the size which accounts for scaling i.e if you draw one pixel in swing it may actually be 2x2 pixels on your screen if your os is set to 200% scaling. As you are using a 4K screen this is highly probable. – weisj Jul 11 '20 at 22:40
  • @weisj Ah, so DisplayMode displays the "real unscaled size" whereas ComponentEvent reports the size with scaling factored in? Hm, so is there a way to determine from DisplayMode what the scaled size would be? Edit: I forgot to mention: I checked, I use 150% scaling so it adds up (kind of). – Snorik Jul 12 '20 at 08:08
  • @camickr thank you for the reminder - the original code is in an invokeLater(), I actually forgot to add this to the example here. – Snorik Jul 12 '20 at 08:11

1 Answers1

0

So the answer really is:

DisplayMode returns the original screen size.
ComponentEvent returns a rectangle that takes scaling of the OS into account.

So that at least is settled.

Snorik
  • 201
  • 3
  • 15