3

图片

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

4

3 回答 3

4

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

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

获得线条方程后,您可以使用动画(可能使用 aSwingWorker或 a )定期SwingTimer增加信封的坐标,然后使用线条方程计算新坐标。xy

我希望这会有所帮助

更新: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();

            }
        });
    }

}
于 2013-08-10T07:21:27.383 回答
3

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

在这个游戏中,敌人每次向玩家前进一行或一列,不计算任何中间点。当目的地静止时,路径是一条直线。动画以javax.swing.Timer. 参见RCModel#move()RCView#timer实现。

于 2013-08-10T07:48:39.780 回答
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));
    }
}

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

于 2013-08-10T07:13:02.723 回答