I am currently wring a card game program. The main class have two different JPanel inner classes. There are at most 10 Field JPanels and 18 Hand JPanels instances occuring at the same time, and each of them has a mouselistener with overriden codes in MousePressed. HOWEVER, every time I click on my card to perform an action, the program has about 2-3 seconds delay before it responds. I used YourKit to analyze the running time and it tells me that the sun.awt.image.ToolkitImage.getWidth(ImageObserver) is taking the longest reponse time (about 3 seconds). I am now really confused why getWidth(null) is so time-consuming. Attached is my paintComponent method and the result from YourKit. YourKit Result
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.WHITE);
Image cardImage = CARD.getCurrentImage().getScaledInstance(getWidth(), getHeight(), Image.SCALE_SMOOTH);
int x = (getWidth() - cardImage.getWidth(null)) / 2;
int y = (getHeight() - cardImage.getHeight(null)) / 2;
g2d.setClip(new RoundRectangle2D.Double(
0, 0, getWidth(), getHeight(), getWidth() / 4, getHeight() / 4));
g2d.drawImage(cardImage, x, y, null);
switch (CARD.getType()){
case Card.FOLLOWER:
Follower follower = (Follower) CARD;
g2d.drawImage(ATK, 15, getHeight() - 60, null);
g2d.drawImage(DEF, getWidth() - 55, getHeight() - 60, null);
AttributedString attack = new AttributedString(Integer.toString(follower.getAttack()));
AttributedString health = new AttributedString(Integer.toString(follower.getHealth()));
attack.addAttribute(TextAttribute.SIZE, 15);
health.addAttribute(TextAttribute.SIZE, 15);
attack.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
health.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
g2d.drawString(attack.getIterator(), 35, getHeight() - 27);
g2d.drawString(health.getIterator(), getWidth() - 35, getHeight() - 27);
if (follower.hasWard()){
g2d.drawImage(WARD, (getWidth() - WARD.getWidth(null)) / 2,
(getHeight() - WARD.getHeight(null)) / 2, this);
}
if (follower.hasAmbush()){
g2d.drawImage(AMBUSH, (getWidth() - AMBUSH.getWidth(null)) / 2,
(getHeight() - AMBUSH.getHeight(null)) / 4, this);
}
if (follower.hasBane()) {
g2d.drawImage(BANE, 10, 10, this);
}
if (follower.hasDrain()){
g2d.drawImage(DRAIN, 50, 10, this);
}
switch (follower.getAtkStatus()){
case Follower.STORM_STAT:
g2d.setColor(Color.GREEN);
g2d.fillOval(getWidth() - 40, 8, 30,30);
g2d.setColor(Color.WHITE);
break;
case Follower.RUSH_STAT:
g2d.setColor(Color.YELLOW);
g2d.fillOval(getWidth() - 40, 8, 30, 30);
g2d.setColor(Color.WHITE);
break;
default:
g2d.setColor(Color.darkGray);
g2d.fillOval(getWidth() - 40, 8, 30, 30);
g2d.setColor(Color.WHITE);
break;
}
break;
case Card.AMULET:
if (((Amulet) CARD).isCountDown()){
g2d.drawString(Integer.toString(((Amulet) CARD).getCountDown()), getWidth() - 50, getHeight() - 50);
}
break;
}
}