如何使JButton与绘制的线一起移动

时间:2013-08-10 06:52:56

标签: java swing timer runnable animated

image

我有Jbutton(由信封表示)和一个Envelope将要行的ArrayList。谁能帮我?任何想法或教程将不胜感激。

3 个答案:

答案 0 :(得分:4)

我假设您的目标是沿着线动画信封,以提供正在传输的数据动画。

对于每条线,首先需要找到线方程。线方程的格式为y = a * x + b。如果您已经在List中提到了那个,那就没关系了。另一方面,如果您有两个点(开始和结束位置),请使用上述等式来查找每一行的ab

在获得线条的方程后,您可以使用动画(可能带有SwingWorkerSwingTimer),这会定期增加信封的x坐标然后使用线方程来计算新的y坐标。

我希望有帮助

更新:使用SwingTimer为演示添加了移动框的代码段

package keymovement;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;

public class TestMovingObject {

    static class Envelope {
        double x;
        double y;

        void setPosition(double x, double y) {
            this.x = x;
            this.y = y;
        }
    }

    static class DrawArea extends JPanel {

        Envelope envelope = new Envelope();

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.red);
            int x = (int) Math.round(envelope.x);
            int y = (int) Math.round(envelope.y);
            g.drawRect(x, y, 20, 20);
        }

        public Envelope getEnvelope() {
            return envelope;
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        SwingUtilities.invokeLater( new Runnable() {

            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

                JFrame window = new JFrame("Moving box");
                window.setPreferredSize(new Dimension(500, 400));
                window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final DrawArea mainArea = new DrawArea();
                window.add(mainArea);
                window.pack();

                window.setLocationRelativeTo(null);
                window.setVisible(true);

                int delay = 20; // execute every 20 milliseconds i.e. 50 times per second  

                Timer timer = new Timer(delay, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        Envelope envelope = mainArea.getEnvelope();
                        double x = envelope.x + 1;  // use smaller increments depending on the desired speed
                        double y = 0.5 * x + 2;     // moving along the line y = 0.5 * x + 2
                        envelope.setPosition(x, y);
                        mainArea.repaint();
                    }
                });
                timer.setRepeats(true);
                timer.start();

            }
        });
    }

}

答案 1 :(得分:3)

你能告诉我一个非常简单的例子吗?

在这个game中,敌人在一次或一列中向玩家前进,而不计算任何中间点。当目的地静止时,路径是直线。动画的节奏为javax.swing.Timer。有关实施,请参阅RCModel#move()RCView#timer

答案 2 :(得分:2)

有一些数学方面的事要做。 看看这篇文章:http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

这个简单的算法会告诉你两点之间一条线上的每个X,Y坐标。您可以使用此算法计算它需要访问的所有位置,将坐标存储在数组中,并在更新位置时迭代数组。

还有一个替代助手类:

package snippet;

import java.awt.geom.Point2D;

public class MyVelocityCalculator {

    public static void main(String[] args) {
        Point2D.Double currentPosition = new Point2D.Double();
        Point2D.Double destinationPosition = new Point2D.Double();
        currentPosition.setLocation(100, 100);
        destinationPosition.setLocation(50, 50);
        Double speed = 0.5;

        System.out.println("player was initially at: " + currentPosition);
        while (currentPosition.getX() > destinationPosition.getX()
                && currentPosition.getY() > destinationPosition.getY()) {

            Point2D.Double nextPosition = MyVelocityCalculator.getVelocity(currentPosition, destinationPosition, speed);
            System.out.println("half seconds later player should be at: " + nextPosition);

            currentPosition = nextPosition;

        }
        System.out.println("player destination is at: " + destinationPosition);

    }

    public static final Point2D.Double getVelocity(Point2D.Double currentPosition, Point2D.Double destinationPosition,
            double speed) {
        Point2D.Double nextPosition = new Point2D.Double();
        double angle = calcAngleBetweenPoints(currentPosition, destinationPosition);
        double distance = speed;
        Point2D.Double velocityPoint = getVelocity(angle, distance);
        nextPosition.x = currentPosition.x + velocityPoint.x;
        nextPosition.y = currentPosition.y + velocityPoint.y;
        return nextPosition;
    }

    public static final double calcAngleBetweenPoints(Point2D.Double p1, Point2D.Double p2) {
        return Math.toDegrees(Math.atan2(p2.getY() - p1.getY(), p2.getX() - p1.getX()));
    }

    public static final Point2D.Double getVelocity(double angle, double speed) {
        double x = Math.cos(Math.toRadians(angle)) * speed;
        double y = Math.sin(Math.toRadians(angle)) * speed;
        return (new Point2D.Double(x, y));
    }
}

不是打印出控制台上的位置,而是需要将此位置的控件绘制到图形元素。