使用paintComponent()和高CPU使用率

时间:2019-06-05 11:17:33

标签: java swing awt

我正在尝试创建一个有趣的游戏,其中包括一个轮子,一个球。每次用户单击按钮时,球都会滚动并随机降落在轮子上的一个插槽中。一切正常,要创建轮子,我将图像和球(椭圆对象)放在单独的{{1} }。功能表现很好,正如我所期望的。但是,每次运行该程序时,CPU都会发出很大的声音,而Java应用程序的使用率通常高达25%。

那太可怕了。经过一段时间的测试后,错误似乎在我的JPanel覆盖的方法内部,因为Java反复不停地调用此方法。更全面的调查表明,问题在于方法painComponent(),该方法用于缩放面板内部的图像。在我看来,如果我删除此方法,getScaledInstance将不会被重复调用。

但是,我不知道如何在没有paintComponent()的情况下缩放图像。请注意,我尝试根据MadProgrammer Java: maintaining aspect ratio of JPanel background image

的示例进行复制

那么,您对此有何看法?有什么方法可以设置背景图像,保持宽高比并且不会过度调用getScaledInstance方法吗?请注意,我确实尝试过使用paintComponent(),但效果并不理想。

这对我来说很挣扎。无论如何,感谢您的阅读!

Thread.sleep

如果尝试运行该程序,您将知道paintComponent被称为不间断。

2 个答案:

答案 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);

}

祝大家好运!