Java 使用paintComponent()和高CPU使用率
我试图创造一个有趣的游戏,其中包括一个轮子,一个球。每次用户点击按钮,球就会滚动并随机落在轮子的一个槽上。一切正常,为了创建轮子,我将图像和球(椭圆形对象)放在一个单独的Java 使用paintComponent()和高CPU使用率,java,swing,awt,Java,Swing,Awt,我试图创造一个有趣的游戏,其中包括一个轮子,一个球。每次用户点击按钮,球就会滚动并随机落在轮子的一个槽上。一切正常,为了创建轮子,我将图像和球(椭圆形对象)放在一个单独的JPanel上。功能性行为如我所期望的那样好。然而,每次我运行程序时,CPU的声音都很大,Java应用程序的使用率通常高达25% 那太可怕了。在做了一些测试之后,错误似乎出现在我的painComponent()重写的方法中,因为Java反复不停地调用这个方法。更全面的调查表明,问题在于用于缩放面板内部图像的方法getScaled
JPanel
上。功能性行为如我所期望的那样好。然而,每次我运行程序时,CPU的声音都很大,Java应用程序的使用率通常高达25%
那太可怕了。在做了一些测试之后,错误似乎出现在我的painComponent()
重写的方法中,因为Java反复不停地调用这个方法。更全面的调查表明,问题在于用于缩放面板内部图像的方法getScaledInstance
。在我看来,如果删除此方法,则不会重复调用paintComponent()
然而,问题是我不知道如何在没有getScaledInstance
的情况下缩放图像。注意,我试图根据MadProgrammer的示例制作一个副本
那么,你觉得怎么样?有没有办法设置背景图像,保持纵横比,并且不过度调用paintComponent()
方法?请注意,我确实尝试过使用Thread.sleep
,但效果不太好
这对我来说是相当困难的。无论如何,谢谢你的阅读
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);
}
}
如果你试着运行这个程序,你就会知道paintComponent被称为不间断的。嗨,我不太懂摇摆,但是你能试着在构造函数中只调用一次
getScaledInstance
来创建图像缩放
//part of the class properties
private Image scaled = null;
//other properties
public WheelPanel() {
this.this_class = this;
try {
image = ImageIO.read(new File("img/Basic_roulette_wheel_1024x1024.png"));
//Create only one scaled image and after that use it in paintComponent method
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));
}
如果由于某种原因,此方法不起作用,您可以尝试在paintComponent
方法中仅创建一个图像缩放
。例如:
//part of the class properties
private Image scaled = null;
/**
* 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()));
int scaleWidth = (int) Math.round(image.getWidth() * scaleFactor);
int scaleHeight = (int) Math.round(image.getHeight() * scaleFactor);
if(scaled == null)
{
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_class);
}
编辑:我看到了如何使用构造函数修改示例。请尝试此构造函数:
//part of the class properties
private Image scaled = null;
public WheelPanel2() {
try {
image = ImageIO.read(new File("img/Basic_roulette_wheel_1024x1024.png"));
} 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);
scaled = image.getScaledInstance(scaleWidth, scaleHeight, Image.SCALE_SMOOTH);
}
祝大家好运 您好,我不太了解swing,但您能否尝试在构造函数中只调用一次
getScaledInstance
来创建图像缩放
//part of the class properties
private Image scaled = null;
//other properties
public WheelPanel() {
this.this_class = this;
try {
image = ImageIO.read(new File("img/Basic_roulette_wheel_1024x1024.png"));
//Create only one scaled image and after that use it in paintComponent method
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));
}
如果由于某种原因,此方法不起作用,您可以尝试在paintComponent
方法中仅创建一个图像缩放
。例如:
//part of the class properties
private Image scaled = null;
/**
* 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()));
int scaleWidth = (int) Math.round(image.getWidth() * scaleFactor);
int scaleHeight = (int) Math.round(image.getHeight() * scaleFactor);
if(scaled == null)
{
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_class);
}
编辑:我看到了如何使用构造函数修改示例。请尝试此构造函数:
//part of the class properties
private Image scaled = null;
public WheelPanel2() {
try {
image = ImageIO.read(new File("img/Basic_roulette_wheel_1024x1024.png"));
} 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);
scaled = image.getScaledInstance(scaleWidth, scaleHeight, Image.SCALE_SMOOTH);
}
祝大家好运 与其自己缩放图像,不如让图形自己缩放,方法是调用: 在大多数平台上,这将利用系统的图形加速来缩放图像 如果要确定缩放图像时使用了等效的“缩放\平滑”,请执行以下操作:
与其自己缩放图像,不如让图形自己缩放,方法是调用: 在大多数平台上,这将利用系统的图形加速来缩放图像 如果要确定缩放图像时使用了等效的“缩放\平滑”,请执行以下操作:
请创建一个,否则我们无法按照您的要求运行您的程序。请修复它。感谢您通知我。获取示例图像(MRE,如@realpoint所述)的一种方法是热链接到中看到的图像。例如,嵌入图像的热链接。请创建一个,否则我们无法按照您的要求运行您的程序。请修复它。感谢您通知我。获取示例图像(MRE,如@realpoint所述)的一种方法是热链接到中看到的图像。例如,与嵌入的图像的热链接。相信我,行为不同;(((我还测试了几次,并将方法放在构造函数上。结果是,虽然没有不间断地调用paintComponent,但其行为与我预期的完全不同。让
paintComponent
被多次调用。如果我理解正确,您的问题是getscaleInstance
被多次调用,并且需要花费大量时间。)大量资源。我的建议是只调用一次getScaledInstance
。请告诉我,当您进行我建议的修改时,您的行为是什么?相信我,行为是不同的(((我还测试了几次,并将方法放在构造函数上。结果是,虽然没有不间断地调用paintComponent,但其行为与我预期的完全不同。让paintComponent
被多次调用。如果我理解正确,您的问题是getscaleInstance
被多次调用,并且需要花费大量时间。)大量资源。我的建议是只调用一次getScaledInstance
。请告诉我,当您进行我建议的修改时,您的行为是什么?但我希望保留图像的纵横比。并且确保在调整面板大小时,此比率是固定的。更新以保留纵横比。但我希望保留图像的纵横比。并确保在调整面板大小时,此比率是固定的。更新以保留纵横比。