I'm doing a basic window that's just filled with an image. My current approach is to create an undecorated JFrame
filled with a JLabel
to which I then apply the image, and then set the frame visible. This performs very well on Windows PC, basically being instantaneous. However, on OS X it performs quite poorly. I get a gray box where the image should be for roughly 1.5-2 seconds, then the image fills in. The Mac I'm using is actually quite a bit faster than my Windows test machine based on profiling the code. The profiler also reveals that it's not my code that's running while we're waiting on the gray screen, so presumably part of the framework or even OS which is unhappy about how/what I'm asking it to do.
So far I've experimented with a variety of different image formats (both source and how I pre-load them in the image) in the hopes of making it render faster, but no change. I've also tried adding pack and repaints in various places to try and hint it into a faster refresh, but no change with that either.
In short, the constructor does this with (BufferedImage image):
final URL imageUrl=new URL(*custom URL here*);
image=ImageIO.read(imageUrl);
Then in setVisible (to avoid the override warnings you get if you do these things in the constructor) we do:
final JLabel bgImage=new JLabel(new ImageIcon(image));
setContentPane(bgImage);
super.setVisible(true);
Not a whole lot to optimize in this process (unless I'm missing a step). Perhaps I'm approaching the problem the wrong way entirely and there is a better/more consistent performing sequence?
MRE
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.imageio.ImageIO;
public class FrameDisplayTime {
private JComponent ui = null;
FrameDisplayTime() {
try {
initUI();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public final void initUI() throws IOException {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
long tStart = System.currentTimeMillis();
BufferedImage image = ImageIO.read(
new URL("https://i.stack.imgur.com/aH5zB.jpg"));
long tLoad = System.currentTimeMillis();
ImageIcon icon = new ImageIcon(image);
JLabel label = new JLabel(icon);
long tIcon = System.currentTimeMillis();
JFrame f = new JFrame(this.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(ui);
ui.add(label);
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
long tDisp = System.currentTimeMillis();
printProperty("os.name");
printProperty("os.version");
printProperty("java.vendor");
printProperty("java.version");
System.out.println("_____________________");
System.out.println("Image load: \t" + (tLoad - tStart));
System.out.println("Icon create: \t" + (tIcon - tLoad));
System.out.println("Frame display: \t" + (tDisp - tIcon));
System.out.println("TOTAL time: \t" + (tDisp - tStart));
}
private static void printProperty(String name) {
System.out.println(String.format(
"%1s:\t%1s", name, System.getProperty(name)));
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
FrameDisplayTime o = new FrameDisplayTime();
};
SwingUtilities.invokeLater(r);
}
}