我正在尝试让JLabel移动到其他JLabel,现在只有1个计时器工作。它应该像火车穿过轨道一样运行,一直绕着轨道行进,最后一直向后从它开始。我不知道如何让它一路走来,任何帮助都表示赞赏。
谢谢。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.JTextField;
import java.awt.Color;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
public class MoveLabel {
private JTextField textField;
private JTextField tf;
private JTextField textField_1;
private JTextField textField_2;
private JTextField textField_3;
private JTextField textField_5;
private JTextField textField_6;
private JTextField textField_7;
private JTextField textField_8;
private JTextField textField_9;
private JTextField textField_10;
private JTextField textField_11;
private JTextField textField_12;
private JTextField textField_13;
private JTextField textField_14;
private JTextField textField_15;
private JTextField textField_16;
private JTextField textField_17;
private JTextField textField_18;
private JTextField textField_19;
private JTextField textField_20;
private JTextField textField_21;
private JTextField textField_22;
private JTextField textField_23;
private JTextField textField_24;
private JTextField textField_25;
private JTextField textField_26;
private JSlider slider;
private JSlider slider_1;
private JSlider slider_2;
public static void main(String[] args) {
new MoveLabel();
}
public MoveLabel() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
TestPane testPane = new TestPane();
testPane.setBackground(Color.WHITE);
frame.getContentPane().add(testPane);
textField = new JTextField();
textField.setBounds(100, 138, 20, 20);
testPane.add(textField);
textField.setColumns(10);
textField_1 = new JTextField();
textField_1.setColumns(10);
textField_1.setBounds(80, 44, 20, 20);
testPane.add(textField_1);
textField_2 = new JTextField();
textField_2.setColumns(10);
textField_2.setBounds(120, 44, 20, 20);
testPane.add(textField_2);
textField_3 = new JTextField();
textField_3.setColumns(10);
textField_3.setBounds(160, 44, 20, 20);
testPane.add(textField_3);
textField_5 = new JTextField();
textField_5.setColumns(10);
textField_5.setBounds(140, 138, 20, 20);
testPane.add(textField_5);
textField_6 = new JTextField();
textField_6.setColumns(10);
textField_6.setBounds(160, 138, 20, 20);
testPane.add(textField_6);
textField_7 = new JTextField();
textField_7.setColumns(10);
textField_7.setBounds(120, 138, 20, 20);
testPane.add(textField_7);
textField_8 = new JTextField();
textField_8.setColumns(10);
textField_8.setBounds(80, 59, 20, 20);
testPane.add(textField_8);
textField_9 = new JTextField();
textField_9.setColumns(10);
textField_9.setBounds(80, 75, 20, 20);
testPane.add(textField_9);
textField_10 = new JTextField();
textField_10.setColumns(10);
textField_10.setBounds(80, 90, 20, 20);
testPane.add(textField_10);
textField_11 = new JTextField();
textField_11.setColumns(10);
textField_11.setBounds(80, 106, 20, 20);
testPane.add(textField_11);
textField_12 = new JTextField();
textField_12.setColumns(10);
textField_12.setBounds(80, 123, 20, 20);
testPane.add(textField_12);
textField_13 = new JTextField();
textField_13.setColumns(10);
textField_13.setBounds(179, 44, 20, 20);
testPane.add(textField_13);
textField_14 = new JTextField();
textField_14.setColumns(10);
textField_14.setBounds(199, 44, 20, 20);
testPane.add(textField_14);
textField_15 = new JTextField();
textField_15.setColumns(10);
textField_15.setBounds(80, 138, 20, 20);
testPane.add(textField_15);
textField_16 = new JTextField();
textField_16.setColumns(10);
textField_16.setBounds(100, 44, 20, 20);
testPane.add(textField_16);
textField_17 = new JTextField();
textField_17.setColumns(10);
textField_17.setBounds(140, 44, 20, 20);
testPane.add(textField_17);
textField_18 = new JTextField();
textField_18.setColumns(10);
textField_18.setBounds(179, 138, 20, 20);
testPane.add(textField_18);
textField_19 = new JTextField();
textField_19.setColumns(10);
textField_19.setBounds(199, 138, 20, 20);
testPane.add(textField_19);
textField_20 = new JTextField();
textField_20.setColumns(10);
textField_20.setBounds(219, 63, 20, 20);
testPane.add(textField_20);
textField_21 = new JTextField();
textField_21.setColumns(10);
textField_21.setBounds(219, 138, 20, 20);
testPane.add(textField_21);
textField_22 = new JTextField();
textField_22.setBackground(Color.WHITE);
textField_22.setColumns(10);
textField_22.setBounds(219, 44, 20, 20);
testPane.add(textField_22);
textField_23 = new JTextField();
textField_23.setColumns(10);
textField_23.setBounds(219, 123, 20, 20);
testPane.add(textField_23);
textField_24 = new JTextField();
textField_24.setColumns(10);
textField_24.setBounds(219, 99, 20, 27);
testPane.add(textField_24);
textField_25 = new JTextField();
textField_25.setColumns(10);
textField_25.setBounds(219, 83, 20, 20);
testPane.add(textField_25);
textField_26 = new JTextField();
textField_26.setColumns(10);
textField_26.setBounds(219, 90, 20, 20);
testPane.add(textField_26);
slider_2 = new JSlider();
slider_2.setMaximum(3);
slider_2.setPaintTicks(true);
slider_2.setSnapToTicks(true);
slider_2.setOrientation(SwingConstants.VERTICAL);
slider_2.setBounds(533, 260, 57, 229);
testPane.add(slider_2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
protected static final int PLAY_TIME = 4000;
private JLabel label;
private JTextField tf;
private int targetX;
private int targetY;
private int targetX2;
private int targetY2;
private long startTime;
private long startTime2;
private final int startX;
private final int startY;
private final int startX2;
private final int startY2;
public TestPane() {
setLayout(null);
tf = new JTextField("");
tf.setSize(20,20);
tf.setBackground(Color.red);
add(tf);
Dimension size = getPreferredSize();
startX = 80;
startY = 44;
/* targetX = (size.width - label.getSize().width) / 2;
targetY = (size.height - label.getSize().height) / 2;
*/
targetX = 140;
targetY = 44;
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int x = tf.getX();
int y = tf.getY();
long duration = System.currentTimeMillis() - startTime;
float progress = (float)duration / (float)PLAY_TIME;
if (progress > 1f) {
progress = 1f;
((Timer)(e.getSource())).stop();
}
x = startX + (int)Math.round((targetX - startX) * progress);
y = startY + (int)Math.round((targetY - startY) * progress);
tf.setLocation(x, y);
}
});
startTime = System.currentTimeMillis();
timer.start();
/* try {
Thread.sleep(10);
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
if (timer.isRunning() != true)
{
timer.stop();
}*/
startX2 = targetX;
startY2 = targetY;
tf.setLocation(startX,startY);
/* targetX = (size.width - label.getSize().width) / 2;
targetY = (size.height - label.getSize().height) / 2;
*/
targetX2 = 219;
targetY2 = 44;
Timer timer2 = new Timer(40, new ActionListener() {
public void actionPerformed(ActionEvent e) {
int x2 = tf.getX();
int y2 = tf.getY();
long duration = System.currentTimeMillis() - startTime2;
float progress = (float)duration / (float)PLAY_TIME;
if (progress > 1f)
{
progress = 1f;
((Timer)(e.getSource())).stop();
}
x2 = startX2 + (int)Math.round((targetX2 - startX2) * progress);
y2 = startY2 + (int)Math.round((targetY2 - startY2) * progress);
tf.setLocation(x2, y2);
tf.getLocation();
}
});
startTime2 = System.currentTimeMillis();
if (timer.isRunning() == false)
{
//
timer2.start();
}
else
{
timer2.setDelay(10);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 500);
}
}
}
答案 0 :(得分:3)
nb:我不喜欢null
布局,我不会宽恕null
布局,我宁愿使用自定义绘画,但是那个'很多与这个问题无关的工作。此示例旨在关注Timeline
和KeyFrame
动画的实现
因为您必须通过x / y位置移动对象,但是在同一时间段内向不同的方向移动,这将成为一个非常复杂的问题......
你可以尝试设置四个链式Timer
,当它们完成时触发下一个Timer
,并且它们都会动画的不同部分......但坦率地说,这就变成了一团糟快......
更好的想法是使用时间线和关键帧的概念。这个想法是,在时间线(0-1)上,某些事件在规定的时间(关键帧)发生。然后时间线将在这些关键帧之间进行混合......
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MoveLabel {
public static void main(String[] args) {
new MoveLabel();
}
public MoveLabel() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
TestPane testPane = new TestPane();
testPane.setBackground(Color.WHITE);
frame.getContentPane().add(testPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private JTextField tf;
private List<JTextField> tracks;
protected static final int PLAY_TIME = 4000;
private Timeline timeline;
private long startTime;
public TestPane() {
setLayout(null);
tracks = new ArrayList<JTextField>(20);
int x = 20;
int y = 20;
for (int index = 0; index < 6; index++) {
x += 20;
tracks.add(createTrack(x, y, 20, 20));
}
for (int index = 0; index < 6; index++) {
y += 20;
tracks.add(createTrack(x, y, 20, 20));
}
for (int index = 0; index < 6; index++) {
x -= 20;
tracks.add(createTrack(x, y, 20, 20));
}
for (int index = 0; index < 6; index++) {
y -= 20;
tracks.add(createTrack(x, y, 20, 20));
}
for (JTextField track : tracks) {
add(track);
}
tf = new JTextField("");
tf.setSize(20, 20);
tf.setBackground(Color.red);
add(tf);
setComponentZOrder(tf, 0);
timeline = new Timeline();
timeline.add(0, new Point(20, 20));
timeline.add(0.25f, new Point(20 * 7, 20));
timeline.add(0.5f, new Point(20 * 7, 20 * 7));
timeline.add(0.75f, new Point(20, 20 * 7));
timeline.add(1f, new Point(20, 20));
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
long duration = System.currentTimeMillis() - startTime;
float progress = (float) duration / (float) PLAY_TIME;
if (progress > 1f) {
startTime = System.currentTimeMillis();
progress = 0;
// ((Timer) (e.getSource())).stop();
}
Point p = timeline.getPointAt(progress);
tf.setLocation(p);
}
});
startTime = System.currentTimeMillis();
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 500);
}
protected JTextField createTrack(int x, int y, int width, int height) {
JTextField field = new JTextField();
field.setBounds(x, y, width, height);
field.setEditable(false);
field.setFocusable(false);
return field;
}
}
public static class Timeline {
private Map<Float, KeyFrame> mapEvents;
public Timeline() {
mapEvents = new TreeMap<>();
}
public void add(float progress, Point p) {
mapEvents.put(progress, new KeyFrame(progress, p));
}
public Point getPointAt(float progress) {
if (progress < 0) {
progress = 0;
} else if (progress > 1) {
progress = 1;
}
KeyFrame[] keyFrames = getKeyFramesBetween(progress);
float max = keyFrames[1].progress - keyFrames[0].progress;
float value = progress - keyFrames[0].progress;
float weight = value / max;
return blend(keyFrames[0].getPoint(), keyFrames[1].getPoint(), 1f - weight);
}
public KeyFrame[] getKeyFramesBetween(float progress) {
KeyFrame[] frames = new KeyFrame[2];
int startAt = 0;
Float[] keyFrames = mapEvents.keySet().toArray(new Float[mapEvents.size()]);
while (startAt < keyFrames.length && keyFrames[startAt] <= progress) {
startAt++;
}
if (startAt >= keyFrames.length) {
startAt = keyFrames.length - 1;
}
frames[0] = mapEvents.get(keyFrames[startAt - 1]);
frames[1] = mapEvents.get(keyFrames[startAt]);
return frames;
}
protected Point blend(Point start, Point end, float ratio) {
Point blend = new Point();
float ir = (float) 1.0 - ratio;
blend.x = (int)(start.x * ratio + end.x * ir);
blend.y = (int)(start.y * ratio + end.y * ir);
return blend;
}
public class KeyFrame {
private float progress;
private Point point;
public KeyFrame(float progress, Point point) {
this.progress = progress;
this.point = point;
}
public float getProgress() {
return progress;
}
public Point getPoint() {
return point;
}
}
}
}
然后你可以做一些愚蠢的事情,比如改变部分之间的速度......
timeline = new Timeline();
timeline.add(0, new Point(20, 20));
timeline.add(0.1f, new Point(20 * 7, 20));
timeline.add(0.5f, new Point(20 * 7, 20 * 7));
timeline.add(0.6f, new Point(20, 20 * 7));
timeline.add(1f, new Point(20, 20));