使用计时器对Java线条图进行动画处理

我试图在面板上绘制两个圆圈,并用一条线将它们连接起来,所有这些都在按下按钮之后完成。到目前为止(除了调整生产线的位置),这还可以。但是,我想使用计时器对其进行动画处理。应该出现第一个圆圈,然后逐渐显示该线,最后是第二个圆圈。

我看过许多计时器的例子,但似乎无法使它对我有用。我一定是误会了。

这是球类(每个圆圈):

package twoBalls;

import java.awt.Color;
import java.awt.Point;

public class Ball {

    private int x;
    private int y;
    private int r;
    private Color color;
    private Point location;
    private Ball parent;

    public Ball(int x, int y, int r) {
        this.x = x;
        this.y = y;
        this.r = r;
        Point p = new Point(x, y);
        setLocation(p);
    }

    public void setParent(Ball b) {
        parent = b;
    }

    public Ball getParent() {
        return parent;
    }

    public void setx(int x) {
        this.x = x;
    }

    public void sety(int y) {
        this.y = y;
    }

    public int getx() {
        return x;
    }

    public int gety() {
        return y;
    }

    public int getr() {
        return r;
    }

    public void setPreferedSize() {

    }

    public void setLocation(Point p) {
        setx(p.x);
        sety(p.y);
        location = p;
    }

    public Point getLocation() {
        return location;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }

}

然后将球存储在arrayList中的类。而且我认为这是应该与计时器一起进行实际绘制的地方。我正在尝试将线条的起点和终点设置为相同,并使用计时器将终点增加到它应该位于的位置。我可能是跟踪的人,但这就是意图!

我已经更改了此类,现在可以在while循环中输入if语句,因为我现在正在比较不同的点。但是,这条线根本还没有画出来。

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();
        }
    }
}

我已经在网上获得了很多帮助,到目前为止,我担心自己的能力超出了我的范围!我不确定下面的EventQueue / run部分。这是设置所有内容的类:

package twoBalls;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

public class Display implements ActionListener {

    private JFrame frame;
    private JButton button;
    private BallsArray b;

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                Display ex = new Display();

            }
        });

    }

    public Display() {
        b = new BallsArray();
        frame = new JFrame();
        frame.setSize(800, 500);
        frame.setTitle("Show balls");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        button = new JButton("New Ball");
        frame.add(button, BorderLayout.SOUTH);
        frame.setVisible(true);
        button.addActionListener(this);

    }

    @Override
    public void actionPerformed(ActionEvent e) {

        Ball ball1 = new Ball(100, 100, 50);
        b.addBall(ball1);
        b.addBall(200, 200, 50);
        frame.add(b, BorderLayout.CENTER);
        frame.revalidate();
        frame.repaint();

    }
}

目前,它绘制了两个圆圈,但根本没有画线。

吉尔伯特·勒布朗克

制作动画时,有助于使用模型/视图/控制器模式

这是我根据您的代码创建的GUI。

显示球动画

我简化了您的Ball课程。这就是定义一个球所需要的。

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;
    }

}

此类包含两个Ball实例,并计算线的长度和方向,分为总增量。

现在我们已经定义了模型类,让我们看一下视图类。第一个是您的Display类。

package twoBalls;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Display implements Runnable {

    private GUIModel guiModel;

    private JFrame frame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Display());
    }

    public Display() {
        this.guiModel = new GUIModel();
        Ball ball1 = new Ball(150, 200, 50, Color.BLUE);
        Ball ball2 = new Ball(450, 200, 50, Color.GREEN);
        guiModel.addBall(ball1);
        guiModel.addBall(ball2);
        guiModel.calculatePoints();
    }

    @Override
    public void run() {
        frame = new JFrame();
        frame.setTitle("Show Balls Animation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        DrawingPanel drawingPanel = new DrawingPanel(guiModel);
        panel.add(drawingPanel, BorderLayout.CENTER);

        panel.add(createButtonPanel(drawingPanel), BorderLayout.SOUTH);

        frame.add(panel);

        frame.pack();
        frame.setVisible(true);
    }

    private JPanel createButtonPanel(DrawingPanel drawingPanel) {
        JPanel panel = new JPanel();

        JButton startButton = new JButton("Start Animation");
        startButton.addActionListener(new StartAnimation(drawingPanel));
        panel.add(startButton);

        return panel;
    }

    public class StartAnimation implements ActionListener {

        private DrawingPanel drawingPanel;

        public StartAnimation(DrawingPanel drawingPanel) {
            this.drawingPanel = drawingPanel;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            LineRunnable runnable = new LineRunnable(drawingPanel);
            new Thread(runnable).start();
        }

    }

}

Display类的构造函数建立了GUI模型。

Display类的run方法构造GUI,并启动动画。

看看我如何分离模型和视图。

StartAnimation类是您的控制器。当您左键单击JButton时,它将启动动画。稍后我将讨论LineRunnable类。

接下来,让我们看一下DrawingPanel类。

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) {

        }
    }

}

在run方法中,我们将线划分为240个段,并每50毫秒绘制一个段。GUI需要12秒钟来绘制线条。您可以根据需要使用这些数字。

for循环是经典的动画循环。首先,您更新模型,这是我在绘图面板中所做的。那你睡吧

此动画循环在不同于GUI线程的线程上运行。这样可以使GUI保持响应状态。由于循环在不同的线程上运行,因此我们必须使用invokeLater方法在事件分发线程上进行绘制。

希望对您有帮助。分而治之。不要让一堂课做不止一件事情。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

我无法使用计时器播放动画

来自分类Dev

使用计时器和数据进行线程处理时出错

来自分类Dev

在python中使用计时器进行基本游戏

来自分类Dev

如何在Java中使用计时器

来自分类Dev

WPF路径从计时器后面的代码中进行动画处理。如何消除动画运行时path元素的摆动?

来自分类Dev

如果动画对象到达特定位置,如何使用计时器停止动画?

来自分类Dev

Java用计时器改变颜色

来自分类Dev

在vb中使用计时器

来自分类Dev

使用计时器移动PictureBox

来自分类Dev

使用计时器的内存泄漏

来自分类Dev

使用计时器限制提问

来自分类Dev

使用计时器逐行读取

来自分类Dev

使用fabric.js对画布中的线条进行动画处理

来自分类Dev

动画发光的 SVG 线条图不能跨浏览器工作

来自分类Dev

如何使用摇摆制作方法,使用计时器进行睡眠

来自分类Dev

用计时器处理类的正确方法是什么?

来自分类Dev

用计时器处理类的正确方法是什么?

来自分类Dev

使用计时器在Navision中进行时间调度

来自分类Dev

在C#中不使用计时器类进行调度

来自分类Dev

如何仅使用计时器进行幻灯片播放

来自分类Dev

使用Java对现有模型进行动画处理?

来自分类Dev

使用Java对多个图像进行动画处理

来自分类Dev

使用Java对现有模型进行动画处理?

来自分类Dev

如何在不使用线程的情况下在Java中使用计时器?

来自分类Dev

如何在不使用线程的情况下在Java中使用计时器?

来自分类Dev

需要多次设置和取消时,如何在Java中使用计时器?

来自分类Dev

使用计时器在Java中创建一般任务

来自分类Dev

java使用计时器更改JOptionPane中JTextArea的内容

来自分类Dev

使用计时器停止另一个计时器

Related 相关文章

热门标签

归档