Reputation: 20638
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, i.e. 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?
Upvotes: 2
Views: 1287
Reputation: 21975
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.
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.
Upvotes: 3
Reputation: 2021
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).
Upvotes: 1
Reputation: 4084
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.
Upvotes: 2