import java.awt.Color; 
import java.awt.Component; 
import java.awt.Graphics; 
import java.awt.image.BufferedImage; 
import javax.swing.JFrame; 

/** 
 * Slow text rendering initialization. 
 * 2-3 second delay on macOS Sierra 
 * Core i7 (2.3 GHz) 
 * 
 */ 
public class Sample { 
static final long initTime = System.nanoTime(); 
static volatile long counter = 0; 

public static void main(String[] args) throws InterruptedException { 

Component comp = new	// uncomment of the following lines 
NoText() 
//	Text() 
//	TextAfter() 
; 


JFrame frame = new JFrame();	
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
frame.add(comp); 
frame.setBounds(100, 0, 500, 500); 
frame.setVisible(true); 

for(int i = 0; i <= 1000; i++){ 
counter = i; 
comp.repaint(); 
Thread.sleep(10); 
} 
} 

} 



/** 
 * Windows without text rendering come up quickly. 
 */ 
class NoText extends Component{ 
static long initTime = System.nanoTime(); 
static long elapsedTime = -1; 

public void paint(Graphics g) { 
g.setColor(Color.GRAY); 
g.fillRect(10, 0, getWidth() - 20, 10); 
if(elapsedTime < 0){ 
elapsedTime = System.nanoTime() - initTime; 
System.out.println((elapsedTime / 1_000_000) + " ms (init .. 1st render [no Text])"); 
} 
} 
} 

/** 
 * Rendering text takes a while the first time. 
 */ 
class Text extends Component{ 
static long initTime = System.nanoTime(); 
static long elapsedTime = -1; 

public void paint(Graphics g) { 
g.drawString("Hello World", 10, 30); 
if(elapsedTime == -1) elapsedTime = System.nanoTime() - initTime; 
g.drawString((elapsedTime / 1_000_000) + " ms (init .. 1st text render)", 10, 50); 
g.setColor(Color.GRAY); 
g.fillRect(10, 0, getWidth() - 20, 10); 
}	
} 

/** 
 * Gets FontMetrics in a separate thread 
 * Start rending non text graphics immediately 
 * Once done the text rendering occurs little delay 
 */ 
class TextAfter extends Component{ 
static long initTime = System.nanoTime(); 
static boolean FONT_INIT = false;	// set true once FontMetric is retrieved 
static long completeTime; 
static long elapsedTime0;	// first rendering (no text) 
static long elapsedTime1;	// FontLoaded 
static long elapsedTime2 = -1;	// first text rendering after FontLoaded 

static{ 
new Thread(() ->{ 
new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY).createGraphics().getFontMetrics(); 
java.awt.EventQueue.invokeLater(() ->{ 
FONT_INIT = true; 
completeTime = System.nanoTime(); 
elapsedTime1 = completeTime - initTime; 
}); 
}).start(); 
} 

public void paint(Graphics g) { 
long width = (getWidth()-20) * Sample.counter / 1000; 
g.setColor(Color.GRAY); 
g.fillRect(10, 0, (int) width, 10); 
if(FONT_INIT){ 
g.setColor(Color.BLACK); 
g.drawString("Hello World", 10, 30); 
if(elapsedTime2 < 0) elapsedTime2 = System.nanoTime() - completeTime; 
g.drawString((elapsedTime0 / 1_000_000) +" ms (init .. 1st render)", 10, 50); 
g.drawString((elapsedTime1 / 1_000_000) +" ms (init .. FontMetrics)", 10, 70); 
g.drawString((elapsedTime2 / 1_000_000) +" ms (FontMetrics .. 1st text render)", 10, 90); 
} 
if(elapsedTime0 < 0) elapsedTime0 = System.nanoTime() - initTime; 
}	
} 