我有Jbutton(由信封表示)和一个Envelope将要行的ArrayList。谁能帮我?任何想法或教程将不胜感激。
答案 0 :(得分:4)
我假设您的目标是沿着线动画信封,以提供正在传输的数据动画。
对于每条线,首先需要找到线方程。线方程的格式为y = a * x + b
。如果您已经在List
中提到了那个,那就没关系了。另一方面,如果您有两个点(开始和结束位置),请使用上述等式来查找每一行的a
,b
。
在获得线条的方程后,您可以使用动画(可能带有SwingWorker
或SwingTimer
),这会定期增加信封的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));
}
}
不是打印出控制台上的位置,而是需要将此位置的控件绘制到图形元素。