Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用paintComponent()和高CPU使用率_Java_Swing_Awt - Fatal编程技术网

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
。请告诉我,当您进行我建议的修改时,您的行为是什么?但我希望保留图像的纵横比。并且确保在调整面板大小时,此比率是固定的。更新以保留纵横比。但我希望保留图像的纵横比。并确保在调整面板大小时,此比率是固定的。更新以保留纵横比。