Search code examples
javaswingtimerrunnableanimated

How to make a JButton move along with drawn lines


image

I have Jbutton (represented by the envelope) and an ArrayList of lines which the Envelope will go along. Can anyone help me? any ideas or tutorial will be much appreciated.


Solution

  • I assume that your goal is to animate the envelope along the line to provide an animation of data being transferred.

    For every line you need first to find the line equation. A line equation is in the form y = a * x + b. If you already have that in the List you mention then that's fine. If on the other hand you have two points instead (start and end positions), use those with the above equation to find a, b for each line.

    After you have the equations for your lines then you can use an animation (probably with a SwingWorker or a SwingTimer) that would increase the x coordinate of your envelope at regular intervals and then use the line equation to calculate the new y coordinate.

    I hope that helps

    Update: Added code snippet for a moving box using a SwingTimer for demonstration

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