使用计时器设置Java线条图的动画
我试着在一个面板上画两个圆圈,用一条线把它们连接起来,所有这些都是在按下一个按钮之后。到目前为止(除了调整线的位置),这还可以。然而,我想用一个定时器来制作动画。第一个圆圈应该出现,然后逐渐显示线条,最后是第二个圆圈 我看过很多计时器的例子,但我似乎无法让它为我工作。我一定是误会了什么 以下是球类(每个圆圈): 然后是将球存储在arrayList中的类。我认为这是实际绘图的地方,还有计时器。 我正在尝试将线的起点和终点设置为相同,并使用计时器递增终点,直到它达到应该的位置。我可能是在追踪,但那是我的意图 我已经更改了这个类,现在可以输入while循环中的if语句,因为我现在正在比较不同的点。但这条线还是没有画出来使用计时器设置Java线条图的动画,java,swing,animation,timer,Java,Swing,Animation,Timer,我试着在一个面板上画两个圆圈,用一条线把它们连接起来,所有这些都是在按下一个按钮之后。到目前为止(除了调整线的位置),这还可以。然而,我想用一个定时器来制作动画。第一个圆圈应该出现,然后逐渐显示线条,最后是第二个圆圈 我看过很多计时器的例子,但我似乎无法让它为我工作。我一定是误会了什么 以下是球类(每个圆圈): 然后是将球存储在arrayList中的类。我认为这是实际绘图的地方,还有计时器。 我正在尝试将线的起点和终点设置为相同,并使用计时器递增终点,直到它达到应该的位置。我可能是在追踪,但那是
package twoBalls;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;
public class BallsArray extends JPanel implements ActionListener {
private ArrayList<Ball> balls;
private Timer timer;
private final int DELAY = 25;
private int xDest;
private int yDest;
private Point dest;
private Point starts;
private int xStart;
private int yStart;
public BallsArray() {
balls = new ArrayList<Ball>();
timer = new Timer(DELAY, this);
yDest = 0;
xDest = 0;
dest = new Point(xDest, yDest);
starts = new Point(xStart, yStart);
}
public void setDestXY(int x, int y) {
xDest = x;
yDest = y;
dest = new Point(xDest, yDest);
setDest(dest);
}
public void setDest(Point p) {
dest = p;
}
public Point getDest() {
return dest;
}
public void setStartsXY(int x, int y) {
xStart = x;
yStart = y;
starts = new Point(xStart, yStart);
setStarts(starts);
}
public void setStarts(Point p) {
starts = p;
}
public Point getStarts() {
return starts;
}
public void addBall(Ball b) {
balls.add(b);
}
public void addBall(int x, int y, int r) {
balls.add(new Ball(x, y, r));
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i < balls.size(); i++) {
if (i == 0) {
paintBall(balls.get(0), g2);
}
if (i != 0) {
int j = i - 1;
Ball bp = balls.get(j);
Ball bc = balls.get(i);
bc.setParent(bp);
paintLine(bc, g2);
paintBall(bc, g2);
}
}
}
public void paintBall(Ball b, Graphics2D g2d) {
Ellipse2D circ = new Ellipse2D.Float(b.getx(), b.gety(), b.getr(),
b.getr());
g2d.draw(circ);
}
public void paintLine(Ball b, Graphics2D g2d) {
timer.start();
if (b != null && b.getLocation() != null) {
Ball parent = b.getParent();
if (parent != null) {
g2d.setColor(Color.GRAY);
if (parent.getLocation() != null && b.getLocation() != null) {
setDest(parent.getLocation());
setStarts(parent.getLocation());
g2d.draw(new Line2D.Float(starts, dest));
}
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
// Not sure what I need to do here
// increment second location somehow
// Point s = getStarts();
Point p = getDest();
Point t = this.getLocation();
while (p != t) {
if (p.x != t.x && p.y != t.y) {
System.out.println("hello");
int x = dest.x;
int y = dest.y;
x++;
y++;
setDestXY(x, y);
p = getDest();
repaint();
} else if (p.x == t.x && p.y != t.y) {
System.out.println("part 2");
int y = dest.y;
y++;
setDestXY(dest.x, y);
p = getDest();
repaint();
} else if (p.x != t.x && p.y == t.y) {
System.out.println("part 3");
int x = dest.x;
x++;
setDestXY(x, dest.y);
p = getDest();
repaint();
}
repaint();
}
}
}
现在它画了两个圆圈,但根本没有画线 制作动画时,使用 这是我根据您的代码创建的GUI 我简化了你的球类课程。这就是定义球所需的全部内容
package twoBalls;
import java.awt.Color;
import java.awt.Point;
public class Ball {
private final int radius;
private final Color color;
private final Point center;
public Ball(int x, int y, int radius, Color color) {
this(new Point(x, y), radius, color);
}
public Ball(Point center, int radius, Color color) {
this.center = center;
this.radius = radius;
this.color = color;
}
public int getRadius() {
return radius;
}
public Color getColor() {
return color;
}
public Point getCenter() {
return center;
}
}
我创建了GUIModel类来保存GUI所需的所有信息。这会将模型与视图分离
package twoBalls;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
public class GUIModel {
private double direction;
private double distance;
private List<Ball> balls;
private Point lineStartPoint;
private Point lineEndPoint;
public GUIModel() {
this.balls = new ArrayList<>();
}
public void addBall(Ball ball) {
this.balls.add(ball);
}
public List<Ball> getBalls() {
return balls;
}
public void calculatePoints() {
this.lineStartPoint = balls.get(0).getCenter();
this.lineEndPoint = balls.get(1).getCenter();
this.distance = Point.distance(lineStartPoint.x, lineStartPoint.y,
lineEndPoint.x, lineEndPoint.y);
this.direction = Math.atan2(lineEndPoint.y - lineStartPoint.y,
lineEndPoint.x - lineStartPoint.x);
}
public Point getCurrentPoint(int pos, int total) {
double increment = distance / total;
double length = increment * pos;
double x = lineStartPoint.x + Math.cos(direction) * length;
double y = lineStartPoint.y - Math.sin(direction) * length;
x = Math.round(x);
y = Math.round(y);
return new Point((int) x, (int) y);
}
public Point getLineStartPoint() {
return lineStartPoint;
}
}
Display类的构造函数设置GUI模型
Display类的run方法构造GUI,并启动动画
package twoBalls;
import java.awt.EventQueue;
public class LineRunnable implements Runnable {
private int total;
private DrawingPanel drawingPanel;
public LineRunnable(DrawingPanel drawingPanel) {
this.drawingPanel = drawingPanel;
this.total = 240;
}
@Override
public void run() {
setDrawLine();
for (int pos = 0; pos <= total; pos++) {
setPos(pos);
sleep(50L);
}
}
private void setDrawLine() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.setDrawLine(true);
drawingPanel.setTotal(total);
}
});
}
private void setPos(final int pos) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.setPos(pos);
}
});
}
private void sleep(long delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
}
}
}
看看我是如何分离模型和视图的
StartAnimation类是您的控制器。当您左键单击JButton时,它将启动动画。稍后我将讨论LineRunnable类
接下来,让我们看看DuffuePAND类。
package twoBalls;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.swing.JPanel;
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -3709678584255542338L;
private boolean drawLine;
private int pos;
private int total;
private GUIModel guiModel;
public DrawingPanel(GUIModel guiModel) {
this.guiModel = guiModel;
this.drawLine = false;
this.setPreferredSize(new Dimension(600, 400));
}
public boolean isDrawLine() {
return drawLine;
}
public void setDrawLine(boolean drawLine) {
this.drawLine = drawLine;
}
public void setPos(int pos) {
this.pos = pos;
repaint();
}
public void setTotal(int total) {
this.total = total;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Ball ball : guiModel.getBalls()) {
g2d.setColor(ball.getColor());
Point center = ball.getCenter();
int radius = ball.getRadius();
g2d.fillOval(center.x - radius, center.y - radius, radius + radius,
radius + radius);
}
if (isDrawLine()) {
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(5.0F));
Point a = guiModel.getLineStartPoint();
Point b = guiModel.getCurrentPoint(pos, total);
g2d.drawLine(a.x, a.y, b.x, b.y);
}
}
}
这个视图类所做的唯一事情就是绘制球和线。计算线路长度的责任属于模型
我在这里设置了首选大小,并使用Display类中的pack方法来获得JFrame的大小。您通常希望知道绘图区域的尺寸,而不是整个窗口的尺寸
最后,让我们看看LineRunnable类。这是控制动画的类
package twoBalls;
import java.awt.EventQueue;
public class LineRunnable implements Runnable {
private int total;
private DrawingPanel drawingPanel;
public LineRunnable(DrawingPanel drawingPanel) {
this.drawingPanel = drawingPanel;
this.total = 240;
}
@Override
public void run() {
setDrawLine();
for (int pos = 0; pos <= total; pos++) {
setPos(pos);
sleep(50L);
}
}
private void setDrawLine() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.setDrawLine(true);
drawingPanel.setTotal(total);
}
});
}
private void setPos(final int pos) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.setPos(pos);
}
});
}
private void sleep(long delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
}
}
}
包两个球;
导入java.awt.EventQueue;
公共类LineRunnable实现Runnable{
私人整数合计;
私人绘图面板绘图面板;
公用线路可运行(DrawingPanel DrawingPanel){
this.drawingPanel=drawingPanel;
这个总数=240;
}
@凌驾
公开募捐{
setDrawLine();
对于(int pos=0;pos谢谢!这对我非常有帮助,尤其是你的解释。如果我想让球在单击按钮之前不会绘制,我会更改DrawingPanel类中的paintComponent方法,使球绘制在另一个If语句中吗?@Ash:是的。我会使用另一个布尔值来表示疼痛t何时绘制球的组件方法。
package twoBalls;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.swing.JPanel;
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -3709678584255542338L;
private boolean drawLine;
private int pos;
private int total;
private GUIModel guiModel;
public DrawingPanel(GUIModel guiModel) {
this.guiModel = guiModel;
this.drawLine = false;
this.setPreferredSize(new Dimension(600, 400));
}
public boolean isDrawLine() {
return drawLine;
}
public void setDrawLine(boolean drawLine) {
this.drawLine = drawLine;
}
public void setPos(int pos) {
this.pos = pos;
repaint();
}
public void setTotal(int total) {
this.total = total;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Ball ball : guiModel.getBalls()) {
g2d.setColor(ball.getColor());
Point center = ball.getCenter();
int radius = ball.getRadius();
g2d.fillOval(center.x - radius, center.y - radius, radius + radius,
radius + radius);
}
if (isDrawLine()) {
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(5.0F));
Point a = guiModel.getLineStartPoint();
Point b = guiModel.getCurrentPoint(pos, total);
g2d.drawLine(a.x, a.y, b.x, b.y);
}
}
}
package twoBalls;
import java.awt.EventQueue;
public class LineRunnable implements Runnable {
private int total;
private DrawingPanel drawingPanel;
public LineRunnable(DrawingPanel drawingPanel) {
this.drawingPanel = drawingPanel;
this.total = 240;
}
@Override
public void run() {
setDrawLine();
for (int pos = 0; pos <= total; pos++) {
setPos(pos);
sleep(50L);
}
}
private void setDrawLine() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.setDrawLine(true);
drawingPanel.setTotal(total);
}
});
}
private void setPos(final int pos) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.setPos(pos);
}
});
}
private void sleep(long delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
}
}
}