我正在尝试创建一个有趣的游戏,其中包括一个轮子,一个球。每次用户单击按钮时,球都会滚动并随机降落在轮子上的一个插槽中。一切正常,要创建轮子,我将图像和球(椭圆对象)放在单独的{{1} }。功能表现很好,正如我所期望的。但是,每次运行该程序时,CPU都会发出很大的声音,而Java应用程序的使用率通常高达25%。
那太可怕了。经过一段时间的测试后,错误似乎在我的JPanel
覆盖的方法内部,因为Java反复不停地调用此方法。更全面的调查表明,问题在于方法painComponent()
,该方法用于缩放面板内部的图像。在我看来,如果我删除此方法,getScaledInstance
将不会被重复调用。
但是,我不知道如何在没有paintComponent()
的情况下缩放图像。请注意,我尝试根据MadProgrammer Java: maintaining aspect ratio of JPanel background image
那么,您对此有何看法?有什么方法可以设置背景图像,保持宽高比并且不会过度调用getScaledInstance
方法吗?请注意,我确实尝试过使用paintComponent()
,但效果并不理想。
这对我来说很挣扎。无论如何,感谢您的阅读!
Thread.sleep
如果尝试运行该程序,您将知道paintComponent被称为不间断。
答案 0 :(得分:2)
通过调用drawImage method which takes width and height arguments,让图形自己来缩放图像,而不是自己缩放图像:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = image.getWidth(this);
int height = image.getHeight(this);
float scale = Math.min(
(float) getWidth() / width,
(float) getHeight() / height);
width = (int) (width * scale);
height = (int) (height * scale);
int x = (getWidth() - width) / 2;
int y = (getHeight() - height) / 2;
g.drawImage(image, x, y, width, height, this);
}
在大多数平台上,这将利用系统的图形加速来缩放图像。
如果要确定使用SCALE_SMOOTH的等效图像来缩放图像,请set the appropriate RenderingHint:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
int width = image.getWidth(this);
int height = image.getHeight(this);
float scale = Math.min(
(float) getWidth() / width,
(float) getHeight() / height);
width = (int) (width * scale);
height = (int) (height * scale);
int x = (getWidth() - width) / 2;
int y = (getHeight() - height) / 2;
g.drawImage(image, x, y, width, height, this);
}
答案 1 :(得分:0)
嗨,我不太了解挥杆动作,但是您可以尝试在构造函数中仅调用getScaledInstance
一次并在那里创建Image scaled
吗?
//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));
}
如果由于某种原因该方法不起作用,则可以尝试在Image scaled
内部仅创建一个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);
}
祝大家好运!