将JLabel移动到其他JLabel – GUI

我正试图让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); } } } 

nb:我不喜欢null布局,我不宽恕null布局,我更喜欢使用自定义绘画,但这是很多与问题无关的工作。 此示例旨在关注TimelineKeyFrame动画的实现

因为你必须通过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 tracks; protected static final int PLAY_TIME = 4000; private Timeline timeline; private long startTime; public TestPane() { setLayout(null); tracks = new ArrayList(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 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)); 

在此处输入图像描述