简体   繁体   中英

Why calling JFrame.pack() after JFrame.setVisible(true) affect the location where JFrame is displayed?

I am compiling and running the following code on Debian 8 with XFCE 4 desktop.

import javax.swing.JFrame;
import javax.swing.JComponent;
import java.awt.EventQueue;
import java.awt.Dimension;
import java.awt.Graphics;

public class FrameDemo
{
    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();
                frame.setLocationByPlatform(true);
                frame.add(new HelloWorldComponent());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

class HelloWorldComponent extends JComponent
{
    public void paintComponent(Graphics g)
    {
        g.drawString("hello, world", 50, 50);
    }

    public Dimension getPreferredSize()
    {
        return new Dimension(200, 100);
    }
}

This produces the desired output. The frame is centered on the desktop.

在此处输入图片说明

But when I move the frame.pack() statement after frame.setVisible(true) statement, ie I pack after I show the frame, I don't see the desired output anymore.

                JFrame frame = new JFrame();
                frame.setLocationByPlatform(true);
                frame.add(new HelloWorldComponent());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
                frame.pack();

The frame is now displayed at the top-left corner of the desktop.

在此处输入图片说明

In fact, the frame does appear in the center of the desktop very briefly for a fraction of a second. After a split second or so, the frame moves to the top-left corner of the desktop.

Why moving the location of the frame.pack() statement change the location where the frame appears on the desktop?

pack() makes a call to setClientSize() that itself makes a call to setBounds(x,y,w,h)

Either way, on my computer, it seems to always be displayed in the top left corner.


Here is your explanation from the JavaDoc about Window#setLocationByPlatform

Calls to setVisible, setLocation and setBounds after calling setLocationByPlatform clear this property of the Window. For example, after the following code is executed:

setLocationByPlatform(true); setVisible(true); boolean flag = isLocationByPlatform(); The window will be shown at platform's default location and flag will be false. In the following sample:

setLocationByPlatform(true); setLocation(10, 10); boolean flag = isLocationByPlatform(); setVisible(true); The window will be shown at (10, 10) and flag will be false.


The alternative

if you want the Window to be centered is to use JFrame#setLocationRelativeTo(null) (it is important to give it null as a parameter).

If the component is null, or the GraphicsConfiguration associated with this component is null, the window is placed in the center of the screen.

pack() eventually calls setBounds(). According to the javadoc for Window,

Calls to setVisible, setLocation and setBounds after calling setLocationByPlatform clear this property of the Window.

Thus the window gets repositioned to the platform's default positioning.

This is because pack() computes the size of the window, which is required to perform the centering calculation correctly. After setting visible, a call to pack() doesn't change window position (but computes the size).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM