为什么在JFrame.setVisible(true)之后调用JFrame.pack()会影响JFrame的显示位置?

时间:2015-12-08 15:36:47

标签: java swing

我正在使用XFCE 4桌面在Debian 8上编译和运行以下代码。

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

这会产生所需的输出。框架以桌面为中心。

enter image description here

但是当我在frame.pack()语句之后移动frame.setVisible(true)语句时,即在显示帧后我打包,我再也看不到所需的输出。

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

框架现在显示在桌面的左上角。

enter image description here

实际上,框架确实会在短时间内出现在桌面的中央,只需几分之一秒。大约一秒钟后,框架移动到桌面的左上角。

为什么移动frame.pack()语句的位置会更改框架在桌面上显示的位置?

3 个答案:

答案 0 :(得分:3)

pack()拨打setClientSize()来调用setBounds(x,y,w,h)

无论哪种方式,在我的电脑上,它似乎总是显示在左上角。

以下是JavaDoc about Window#setLocationByPlatform

的解释
  

调用后调用setVisible,setLocation和setBounds   setLocationByPlatform清除Window的这个属性。例如,   执行以下代码后:

     

setLocationByPlatform(真);调用setVisible(真);布尔标志=   isLocationByPlatform();窗口将显示在平台上   默认位置和标志将为false。在以下示例中:

     

setLocationByPlatform(真); setLocation(10,10);布尔标志=   isLocationByPlatform();调用setVisible(真);将显示该窗口   在(10,10)和旗帜将是假的。

替代

如果您希望将窗口置于中心位置,则使用JFrame#setLocationRelativeTo(null)(将null作为参数设置非常重要。)

  

如果组件为null,或者与GraphicsConfiguration关联   此组件为null,窗口位于中心   屏幕。

答案 1 :(得分:2)

pack()最终调用setBounds()。根据Window的javadoc,

  

调用后调用setVisible,setLocation和setBounds   setLocationByPlatform清除Window的这个属性。

因此窗口重新定位到平台的默认定位。

答案 2 :(得分:1)

这是因为pack()计算窗口的大小,这是正确执行居中计算所需的。设置可见后,对pack()的调用不会更改窗口位置(但会计算大小)。