Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
268 views
in Technique[技术] by (71.8m points)

java - Moving JLabel to other JLabels - GUI

I'm trying to make a JLabel move across other JLabels, only 1 timer works right now. It is supposed to operate like a train moving across a track, going all the way around the track and ending up right back where it started from. I'm not sure how to make it go all the way around, any help is appreciated.

Thank you.

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();


                }
            });
            startTime

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

nb: I don't like null layouts, I don't condone null layouts, I would prefer to have used custom painting, but that's a lot of work not related to the question. This example is intended to focus on the implementation of a Timeline and KeyFrame animation

Because you have to move the object through both the x/y positions, but in different directions over the same time period, this becomes a very complex problem...

You could try and set up four, chained Timers, which trigger the next Timer when they complete, and which all do a different part of the animation...but frankly, that becomes a mess real quick...

A better idea is to use a concept of a time line and key frames. The idea is, that over the time line (0-1), certain events occur at prescribed times (key frames). The time line will then blend between these key frames...

enter image description here

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;
            }

        }

    }
}

You could then do silly things like vary the speed between sections...

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));

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...