0

I am having difficulties displaying a JFrame with all of the contents showing immediately. I would like to show the JFrame with all Components already added, but the window appears to become visible out-of-focus, wait a second, then come into focus with the Component(s) added. The code for my SSCCE is extremely short/simple, so I don't know why this effect is happening.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DelayTest
{
    public static void main(String[] args)
    {
        JLabel label = new JLabel("DELAY TEST");
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setPreferredSize(new Dimension(400, 60));
        JFrame frame = new JFrame("Delay Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(label);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

I know that this effect does not happen if I comment out label.setPreferredSize(new Dimension(400,60));, so though it may simply be a correlation & not a causation, I'm guessing somehow PreferredSizes have to do with it. But, why?

ALSO, this effect occurs even if I create the GUI in a separate Runnable thread apart from the main thread. Although clearly the effect is related to the order of thread execution, I do not believe that specific factor is the cause.

Upon startup:

enter image description here

About 1 second later:

enter image description here

Scott Hetrick
  • 161
  • 1
  • 10

1 Answers1

1

The likely delay is caused by the need for the system to initialize the synchronize the Event Dispatching Thread with the native system before it can render content.

You should make sure that your UI is initialised and shown from within the context of the Event Dispatching Thread, which should make the initial startup more synchronised...

enter image description here

Take a look at Initial Threads for more details

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestDelay {

    public static void main(String[] args) {
        new TestDelay();
    }

    public TestDelay() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JLabel label = new JLabel("Delay Test");
                Font font = label.getFont();
                label.setFont(font.deriveFont(Font.BOLD, 24f));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(label);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • However, if `label.setPreferredSize(new Dimension(400,60));` is added directly after `label.setFont(font.deriveFont(Font.BOLD, 24f));`, the exact same problem occurs. Even in my code, commenting out the line where I call `setPreferredSize()` on the `JLabel` fixes the issue. What I want to know is how the issue can be resolved _without_ removing the setting of the `Component`'s `preferredSize`. – Scott Hetrick Jan 08 '15 at 23:58
  • Why are you using `setPreferredSize`? – MadProgrammer Jan 09 '15 at 00:01
  • The program I want to use this for has a GUI with a number of components, all of which I would like to have starting out at their `preferredSize`s. This is the simplest SSCCE I could think of to replicate it. – Scott Hetrick Jan 09 '15 at 00:03
  • 1
    [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?](http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi) – MadProgrammer Jan 09 '15 at 00:05
  • So is that to say that there's no way to solve the problem except to avoid it? – Scott Hetrick Jan 09 '15 at 01:05
  • This probably has something to do with the way the Mac is rendering the text, but's it little hard to diagnose. Generally speaking you should avoid using `setPreferredSize` and simply let the component calculate it's required size itself. You could use a combination of `Border` and `LayoutManager`s to adjust the amount of space around components...which will appear better on systems that use different fonts and rendering pipelines which could change the amount of space that a component might need – MadProgrammer Jan 09 '15 at 01:10
  • It just seems like it's so trivial.. After the initial startup, if I make the `JFrame` invisible again & then open it later, all components are present with no delay. I have been able to modify the code to where the `JFrame` appears with the click of a `JButton`, & it works fine when on the Event Dispatch Thread, I suppose. – Scott Hetrick Jan 09 '15 at 01:37
  • Again, the problem with messing with `preferredSize` of components is that it doesn't take into situations where the resolution/DPI/font metrics/rendering pipelines differ between systems...best not to mess with it and work within the available API – MadProgrammer Jan 09 '15 at 01:39