Performance 用Java绘图-为什么我的代码这么慢?
背景 我正在尝试创建一个花哨、平滑、快速的模拟仪表,带有一些刻度盘惯性模拟等。如果可能的话,我想避免使用OpenGL 问题 我的Java代码比我预期的慢得多 我希望我的拨号盘从最小值(0)移动到最大值(1024,我可以更改,但我需要平滑度)的时间短于0.5秒 我试图测量重新绘制和绘制组件方法所花费的时间,以发现问题 在我的机器上(Core Duo 2GHz,Windows 7),重新喷漆大约需要40us,喷漆组件需要300us 它似乎足够快(1/0.000340s=每秒约3000次“运行”) 我认为视频卡是一个瓶颈,它会减慢我的代码速度,但我不知道如何处理它 问题 如何使我的代码更快,并尽可能保持动画流畅Performance 用Java绘图-为什么我的代码这么慢?,performance,graphics,java-7,Performance,Graphics,Java 7,背景 我正在尝试创建一个花哨、平滑、快速的模拟仪表,带有一些刻度盘惯性模拟等。如果可能的话,我想避免使用OpenGL 问题 我的Java代码比我预期的慢得多 我希望我的拨号盘从最小值(0)移动到最大值(1024,我可以更改,但我需要平滑度)的时间短于0.5秒 我试图测量重新绘制和绘制组件方法所花费的时间,以发现问题 在我的机器上(Core Duo 2GHz,Windows 7),重新喷漆大约需要40us,喷漆组件需要300us 它似乎足够快(1/0.000340s=每秒约3000次“运行”) 我
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Main extends JPanel {
private static final Point2D CENTER = new Point2D.Double(PREF_W / 2.0,
PREF_W / 2.0);
private static final double RADIUS = PREF_W / 2.0;
private static final Color LARGE_TICK_COLOR = Color.DARK_GRAY;
private static final Color CENTER_HUB_COLOR = Color.DARK_GRAY;
private static final Stroke LARGE_TICK_STROKE = new BasicStroke(4f);
private static final Stroke LINE_TICK_STROKE = new BasicStroke(8f);
private static final int LRG_TICK_COUNT = 18;
private static final double TOTAL_LRG_TICKS = 24;
private static final double LRG_TICK_OUTER_RAD = 0.9;
private static final double LRG_TICK_INNER_RAD = 0.8;
private static final int START_TICK = 10;
private static final double CENTER_HUB_RADIUS = 10;
private static final double DIAL_INNER_RAD = 0.00;
private static final double DIAL_OUTER_RAD = 0.75;
private static final Color DIAL_COLOR = Color.DARK_GRAY;
private BufferedImage backgroundImg;
private static final int PREF_W = 400; //
private static final int PREF_H = 400;
private static final double INIT_VALUE = 0;
public static final int MAX_VALUE = 1024; // resolution
public static int delay = 1; // delay (ms) between value changes
private double theta;
private double cosTheta;
private double sinTheta;
private static long microtime;
public Main() {
setBackground(Color.white);
backgroundImg = createBackgroundImg();
setSpeed(INIT_VALUE);
}
public void setSpeed(double speed) {
if (speed < 0) {
speed = 0;
} else if (speed > MAX_VALUE) {
speed = MAX_VALUE;
}
this.theta = ((speed / MAX_VALUE) * LRG_TICK_COUNT * 2.0 + START_TICK)
* Math.PI / TOTAL_LRG_TICKS;
cosTheta = Math.cos(theta);
sinTheta = Math.sin(theta);
microtime = System.nanoTime()/1000;
repaint();
System.out.println("Repaint (us) = " + (System.nanoTime()/1000 - microtime));
}
private BufferedImage createBackgroundImg() {
BufferedImage img = new BufferedImage(PREF_W, PREF_H,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(LARGE_TICK_COLOR);
g2.setStroke(LARGE_TICK_STROKE);
for (double i = 0; i < LRG_TICK_COUNT; i++) {
double theta = (i * 2.0 + START_TICK) * Math.PI / TOTAL_LRG_TICKS;
double cosTheta = Math.cos(theta);
double sinTheta = Math.sin(theta);
int x1 = (int) (LRG_TICK_INNER_RAD * RADIUS * cosTheta + CENTER.getX());
int y1 = (int) (LRG_TICK_INNER_RAD * RADIUS * sinTheta + CENTER.getY());
int x2 = (int) (LRG_TICK_OUTER_RAD * RADIUS * cosTheta + CENTER.getX());
int y2 = (int) (LRG_TICK_OUTER_RAD * RADIUS * sinTheta + CENTER.getY());
g2.drawLine(x1, y1, x2, y2);
}
g2.setColor(CENTER_HUB_COLOR);
int x = (int) (CENTER.getX() - CENTER_HUB_RADIUS);
int y = (int) (CENTER.getY() - CENTER_HUB_RADIUS);
int width = (int) (2 * CENTER_HUB_RADIUS);
int height = width;
g2.fillOval(x, y, width, height);
g2.dispose();
return img;
}
@Override
protected void paintComponent(Graphics g) {
System.out.println("Paint component (us) = " + (System.nanoTime()/1000 - microtime));
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, this);
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(LINE_TICK_STROKE);
g.setColor(DIAL_COLOR);
int x1 = (int) (DIAL_INNER_RAD * RADIUS * cosTheta + CENTER.getX());
int y1 = (int) (DIAL_INNER_RAD * RADIUS * sinTheta + CENTER.getY());
int x2 = (int) (DIAL_OUTER_RAD * RADIUS * cosTheta + CENTER.getX());
int y2 = (int) (DIAL_OUTER_RAD * RADIUS * sinTheta + CENTER.getY());
g.drawLine(x1, y1, x2, y2);
microtime = System.nanoTime()/1000;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
final Main mainPanel = new Main();
JFrame frame = new JFrame("DailAnimation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
new Timer(delay, new ActionListener() {
double speed = 0;
@Override
public void actionPerformed(ActionEvent evt) {
speed ++;
if (speed > Main.MAX_VALUE) {
speed = 0;
}
mainPanel.setSpeed(speed);
}
}).start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
import java.awt.BasicStroke;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.Stroke;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.geom.Point2D;
导入java.awt.image.buffereImage;
导入javax.swing.*;
公共类Main扩展了JPanel{
专用静态最终点2D中心=新点2D.Double(PREF_W/2.0,
PREF_W/2.0);
专用静态最终双半径=PREF_W/2.0;
私有静态最终颜色大\勾号\颜色=颜色。深\灰色;
专用静态最终颜色中心\u中心\u颜色=Color.DARK\u灰色;
专用静态最终冲程大刻度冲程=新基本冲程(4f);
专用静态最终冲程线\刻度\冲程=新基本冲程(8f);
私有静态最终整数LRG_TICK_COUNT=18;
私人静态最终双倍总刻度=24;
专用静态最终双LRG_刻度_外部_弧度=0.9;
专用静态最终双LRG_刻度_内部_弧度=0.8;
专用静态最终整数开始_TICK=10;
专用静态最终双中心轮毂半径=10;
专用静态最终双拨盘_内部_RAD=0.00;
专用静态最终双拨盘_外部_RAD=0.75;
专用静态最终颜色刻度盘颜色=颜色。深灰色;
私有缓冲区图像背景;
私有静态最终整型参数W=400;//
私有静态最终整型参数H=400;
私有静态最终双初始值=0;
公共静态最终int MAX_值=1024;//分辨率
public static int delay=1;//值更改之间的延迟(毫秒)
私人双θ;
私人双科斯特塔;
私人双辛赫塔;
私有静态长微时间;
公用干管(){
挫折地面(颜色:白色);
backgroundImg=createBackgroundImg();
设置速度(初始值);
}
公共无效设置速度(双速){
如果(速度<0){
速度=0;
}否则如果(速度>最大值){
速度=最大值;
}
this.theta=((速度/最大值)*LRG\u刻度线计数*2.0+开始刻度线)
*Math.PI/总刻度;
cosTheta=数学cos(θ);
sinTheta=Math.sin(θ);
microtime=System.nanoTime()/1000;
重新油漆();
System.out.println(“重新绘制(us)=”+(System.nanoTime()/1000-microtime));
}
私有缓冲区映像createBackgroundImg(){
BuffereImage img=新的BuffereImage(预镜像,预镜像,
BuffereImage.TYPE_INT_ARGB);
Graphics2D g2=img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_抗锯齿,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.设置颜色(大刻度颜色);
g2.设定行程(大行程);
对于(双i=0;i