I am trying to create a funny game, which includes a Wheel, a ball. Each time the user click on the button, the ball will roll and randomly land on one slot in the wheel.Things are OK, to create the Wheel, I put the image and the ball (Oval Object) on a separate JPanel
. The functional behavior are good as i expect. However, each time i run the program, the CPU sounds loudly and the usage of Java application often take up to 25%.
That's quite terrible. After a while doing some tests, it seems that the error is inside my painComponent()
overridden methods as the Java repeatedly call this method nonstop. A more throughout investigation suggest the the problem is the method getScaledInstance
which is used to scale the image inside panel. It appears to me that if i remove this method, the paintComponent()
will not be called repeatedly.
However, things are I don't know how to make the image scaled without getScaledInstance
. Note that I tried to make a copy based on the sample of MadProgrammer Java: maintaining aspect ratio of JPanel background image
So, what do you think about it? Is there any way to set the background image, keep the aspect ratio and not over calling paintComponent()
method? Note that I did try to use Thread.sleep
but it doesn't work very well.
This is quite struggling for me. Anyway, thank for reading!
public class WheelPanel2 extends JPanel {
private BufferedImage image;
private int time = 0;
private Image scaled = null;
private int scaleWidth = 300;
private int scaleHeight = 300;
public WheelPanel2() {
try {
image = ImageIO.read(new File("img/Basic_roulette_wheel_1024x1024.png"));
scaled = image.getScaledInstance(scaleWidth, scaleHeight, Image.SCALE_SMOOTH);
} catch (IOException e) {
e.printStackTrace();
}
setSize(400, 400);
setPreferredSize(new Dimension(400, 400));
setBorder(BorderFactory.createLineBorder(Color.BLACK));
double scaleFactor = Math.min(1d, getScaleFactorToFit(new Dimension(image.getWidth(), image.getHeight()), getSize()));
int scaleWidth = (int) Math.round(image.getWidth() * scaleFactor);
int scaleHeight = (int) Math.round(image.getHeight() * scaleFactor);
Image scaled = image.getScaledInstance(scaleWidth, scaleHeight, Image.SCALE_SMOOTH);
}
/**
* The Paint Method - Create the image of the Wheel and the Ball
*/
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
double scaleFactor = Math.min(1d, getScaleFactorToFit(new Dimension(image.getWidth(), image.getHeight()), getSize()));
//TRUE WIDTH AND HEIGHT
int scaleWidth = (int) Math.round(image.getWidth() * scaleFactor);
int scaleHeight = (int) Math.round(image.getHeight() * scaleFactor);
scaled = image.getScaledInstance(scaleWidth, scaleHeight, Image.SCALE_SMOOTH);
int width = getWidth() - 1;
int height = getHeight() - 1;
int x = (width - scaled.getWidth(this)) / 2;
int y = (height - scaled.getHeight(this)) / 2;
g.drawImage(scaled, x, y, this);
System.out.println("PAINT");
}
/**
* These two methods are used to automatically resize the wheelpanel and the ball
*/
private double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
private double getScaleFactor(int iMasterSize, int iTargetSize) {
double dScale;
if (iMasterSize > iTargetSize) {
dScale = (double) iTargetSize / (double) iMasterSize;
} else {
dScale = (double) iTargetSize / (double) iMasterSize;
}
return dScale;
}
public static void main (String[] args) {
JFrame frame = new JFrame("HI THERE");
frame.setSize(1000, 1000);
frame.setLayout(new BorderLayout());
frame.add(new WheelPanel2(), BorderLayout.CENTER);
frame.setVisible(true);
frame.setDefaultCloseOperation(1);
}
}
If you try to run the program, you will know that the paintComponent are called non-stop.