为什么我的java动画占用了我的整个CPU

时间:2016-02-25 00:18:52

标签: java swing animation

我做了一个显示光波干涉图案的程序。我通过在JPanel上使用paint方法绘制2个源,然后在它们周围绘制同心圆来完成此操作。这将是双缝干涉,所以我允许其中一个光源移动以试验狭缝宽度。

问题在于,当我运行它时,我的电脑说它正在使用80%的CPU!真的不是很多。在中间圈,围绕它旋转,然后移动。我的代码如下。

主要课程:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;


public class main {
static final int UP = -1;
static final int DOWN = 1;
static final int RIGHT = 1;
static final int LEFT = -1;
static final int NOMOVEMENT = 0;


static int verticalMovement = NOMOVEMENT;
static int horizontalMovement = NOMOVEMENT;
public static void main(String[] args) {
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

    Point s1 = new Point((int)(screenSize.getWidth()/3), 50);
    Point s2 = new Point((int)(2*screenSize.getWidth()/3), 50);

    JFrame frame = new JFrame("Physics Frame");
    frame.setPreferredSize(screenSize);

    PhysicsPane pane = new PhysicsPane(screenSize, 15, s1, s2);
    pane.setPreferredSize(screenSize);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(pane);
    frame.pack();

    Timer time = new Timer(1000 / 20, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            switch (verticalMovement){
                case UP:
                    s2.changeY(UP);
                    break;
                case DOWN:
                    s2.changeY(DOWN);
                    break;
                default:
                    break;
            }
            switch (horizontalMovement){
                case RIGHT:
                    s2.changeX(RIGHT);
                    break;
                case LEFT:
                    s2.changeX(LEFT);
                    break;
                default:
                    break;
            }
            pane.repaint();
        }
    });

    frame.addKeyListener(new KeyListener() {
        @Override
        public void keyTyped(KeyEvent e) {
        }

        @Override
        public void keyPressed(KeyEvent e) {
            if(e.getKeyCode()==37){
                horizontalMovement = LEFT;
            } else if (e.getKeyCode()==38){
                verticalMovement = UP;
            } else if (e.getKeyCode()==39){
                horizontalMovement = RIGHT;
            } else if (e.getKeyCode()==40){
                verticalMovement = DOWN;
            }

            if(e.getKeyChar()=='a'){
                pane.setWaveLength(2);
            }
            if(e.getKeyChar()=='s'){
                pane.setWaveLength(-2);
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            switch (e.getKeyCode()){
                case 37:
                    horizontalMovement = NOMOVEMENT;
                    break;
                case 38:
                    verticalMovement = NOMOVEMENT;
                    break;
                case 39:
                    horizontalMovement = NOMOVEMENT;
                    break;
                case 40:
                    verticalMovement = NOMOVEMENT;
                    break;
            }
        }
    });
    frame.setVisible(true);
    time.start();

}
}

小组课程。如果使用绘图方法效率低下,它就在这里。

import javax.swing.*;
import java.awt.*;

public class PhysicsPane extends JPanel {
private Dimension size;
private Point[] pointArray = new Point[2];
private double waveLength;
public PhysicsPane(Dimension size, double wavelength, Point source1, Point source2) {
    this.size = size;
    pointArray[0] = source1;
    pointArray[1] = source2;
    setPreferredSize(size);
    this.waveLength = wavelength;
}

@Override
public void paintComponent(Graphics g){
    for (int i = 0; i < 2; i++) {
        g.setColor(Color.black);
        double x = this.pointArray[i].getX();
        double y = this.pointArray[i].getY();
        g.fillOval((int)x, (int)y, 2, 2);
        for (int j = (int)waveLength; j < 1500; j+=waveLength) {
            g.setColor(Color.red);
            g.drawOval((int)x-(j/2+1), (int)y-(j/2+1), 2 + j, 2 + j);
        }
    }
}

public void setWaveLength(double increment){
    this.waveLength+=increment;
}
}

点类:真的只是将x和y坐标放入一个构造中。特别重要

public class Point {
private double x;
private double y;

public Point(double x, double y) {
    this.x = x;
    this.y = y;
}

public double getX() {
    return x;
}

public void setX(double x) {
    this.x = x;
}

public double getY() {
    return y;
}

public void setY(double y) {
    this.y = y;
}

public void changeX(double dX){
    this.x+=dX;
}

public void changeY(double dY){
    this.y+=dY;
}
}

那我的程序出了什么问题?为什么这么简单的动画消耗了我的处理器呢?

更新的代码部分:

@Override
public void paintComponent(Graphics g){
    BufferedImage bi = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
    Graphics graphics = bi.getGraphics();
    for (int i = 0; i < 2; i++) {
        graphics.setColor(Color.black);
        double x = this.pointArray[i].getX();
        double y = this.pointArray[i].getY();
        graphics.fillOval((int)x, (int)y, 2, 2);
        for (int j = (int)waveLength; j < 1500; j+=waveLength) {
            graphics.setColor(Color.red);
            graphics.drawOval((int)x-(j/2+1), (int)y-(j/2+1), 2 + j, 2 + j);
        }
    }
    g.drawImage(bi, 0, 0, new ImageObserver() {
        @Override
        public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
            return false;
        }
    });
}

1 个答案:

答案 0 :(得分:1)

我建议的改进是删除正在执行的不必要的任务,特别是代码如何更新正在绘制的窗格,即使没有更改。

以下更新将CPU使用率从12%降低到0%(静态帧):

recyclerView