我有一个简单的程序,它以一定的速度和角度绘制从原点发射的粒子的轨迹。我创建了一个JPanel的子类来处理这个的绘制。我每次重新绘制子类时都需要当前时间和初始时间之间的差值(以毫秒为单位),将其转换为秒,然后找到粒子应该在该时间点的x和y坐标,最后获取那些x和y坐标并在屏幕上绘制它们。我的问题是我的子类似乎在间隔时间重新绘制,因为只显示了几个点。
我的绘图方法:
private void doDrawing(Graphics g) {
Dimension size = getSize();
Insets insets = getInsets();
int w = size.width - insets.left - insets.right;
int h = size.height - insets.top - insets.bottom;
Graphics2D g2d = (Graphics2D) g;
g.drawString("Acceleration: -9.8m/s i", 0, 20);
StringBuilder b = new StringBuilder();
b.append("Current Velocity: ");
b.append(String.valueOf(sim.getVector(tickSpeed
* ((System.currentTimeMillis() - initTime) / 1000)).getMagnitude()));
b.append(" m/s at ");
b.append(String.valueOf(sim.getVector(tickSpeed
* ((System.currentTimeMillis() - initTime) / 1000)).getDirection().getDirectionDeg()));
b.append(" degrees");
g.drawString(b.toString(), 0, 30);
drawPreviousPoints(g2d);
drawCurrentPointAndAppend(g2d, w, h);
repaint();
}
private void drawCurrentPointAndAppend(Graphics2D g2d, int w, int h) {
g2d.setColor(Color.red);
double height = (length / w) * h;
Vector2D c = sim.getVector(tickSpeed
* ((System.currentTimeMillis() - initTime) / 1000));
double currentX = w
* ((sim.getX(tickSpeed
* ((System.currentTimeMillis() - initTime) / 1000))) / length);
double currentY = h
* (1 - ((sim.getY(tickSpeed
* ((System.currentTimeMillis() - initTime) / 1000))) / height));
g2d.drawLine((int) currentX, (int) currentY, (int) currentX,
(int) currentY);
g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_MITER));
g2d.drawLine((int) currentX, (int) (currentY),
(int) (currentX + w * (c.getX() / length)),
(int) (currentY + (h * -(c.getY() / height))));
xList.add(currentX);
yList.add(currentY);
}
private void drawPreviousPoints(Graphics2D g2d) {
g2d.setColor(Color.blue);
g2d.setStroke(new BasicStroke(7, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND));
if (!xList.isEmpty()) {
for (int i = 0; i < xList.size(); i++) {
g2d.drawLine(xList.get(i).intValue(), yList.get(i).intValue(),
xList.get(i).intValue(), yList.get(i).intValue());
}
}
}
tickSpeed只是我用来加速或减慢粒子的变量。它运行良好;然而,动画似乎很不稳定。
答案 0 :(得分:5)
Swing的一个重要规则 - 你不能控制油漆过程......
不要在paintComponent
内执行这些计算。 paintComponent
用于绘制UI的当前状态,并且可能由于多种原因随时被调用,其中大部分都在您无法控制的范围内。
相反,请考虑使用javax.swing.Timer
设置以固定间隔重复(40毫秒是每秒25个滴答)。
设置一个模型,跟踪当前处理的粒子。计时器滴答时,计算粒子位置并更新它们,然后调用repaint
。
在paintComponent
中,只需绘制模型的当前状态。
有关详细信息,请查看Concurrency in Swing和How to use Swing Timers
答案 1 :(得分:1)
绘制过程在内部处理,因此您无法控制其执行频率。 但是,您可以创建单独的线程或计时器,它们可以按您所需的频率调用进程。仅使用paint方法在画布上渲染,在其他函数中执行其他逻辑和处理。