user3037561
user3037561

Reputation: 271

Java graphic not painting properly

I've written the following code

   import java.awt.BorderLayout;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

final public class Test
{

    JFrame frame;
    DrawPanel drawPanel;
    boolean up = false;
    boolean down = true;
    boolean left = false;
    boolean right = true;
    private int timeStep = 0;
    private int ballYTravel = 100;
    private int BALL_NUM = 24;

    public static void main(String... args)
    {
        new Test().go();
    }

    private void go()
    {
        frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        drawPanel = new DrawPanel();

        frame.getContentPane().add(BorderLayout.CENTER, drawPanel);

        frame.setResizable(false);
        frame.setSize(800, 600);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        moveIt();
    }

    class DrawPanel extends JPanel
    {
        private static final long serialVersionUID = 1L;
        public double getY(int i, int t) {
            return 200 + ballYTravel / 2 * (Math.sin(timeStep * (i / 200 + 0.08)));
        }

        public void paintComponent(Graphics g)
        {    
            for (int k = 0; k < BALL_NUM; k++ ) {
                g.fillRect(100  + 20 *k , (int) getY(k, timeStep), 6, 6);
            }
            timeStep++;

        }
    }



    private void moveIt()
    {
        while (true)
        {

            try
            {
                Thread.sleep(10);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            frame.repaint();
        }
    }
    }

It runs and animates, however it is not animating in the same fashion as the Javascript code I referenced it from which can be found here http://codepen.io/anon/pen/ZYQoQZ

any help in understanding why is appreciated

Upvotes: 1

Views: 97

Answers (2)

trashgod
trashgod

Reputation: 205775

Your transliteration reveals several problems:

Revised code, incorporating @Mad's fix and using drawOval():

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
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.Timer;

final public class Test {

    JFrame frame;
    DrawPanel drawPanel;
    private int timeStep = 0;
    private int ballYTravel = 100;
    private int BALL_NUM = 24;

    public static void main(String... args) {
        new Test().go();
    }

    private void go() {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                drawPanel = new DrawPanel();
                frame.add(BorderLayout.CENTER, drawPanel);
                frame.setResizable(false);
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
                Timer t = new Timer(10, new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        drawPanel.repaint();
                    }
                });
                t.start();
            }
        });
    }

    private class DrawPanel extends JPanel {

        public double getY(int i, int t) {
            return 200 + ballYTravel / 2 * (Math.sin(t * (i / 200d + 0.08)));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (int k = 0; k < BALL_NUM; k++) {
                g.drawOval(100 + 20 * k, (int) getY(k, timeStep), 8, 8);
            }
            timeStep++;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(700, 500);
        }

    }
}

Upvotes: 5

MadProgrammer
MadProgrammer

Reputation: 347184

There are (possibly) two basic problems...

  1. In getY, you are ignoring the parameter t and using timeStep instead, while, technically, this probably isn't going to make a MASSIVE difference, it is an area of concern
  2. You have an integer division issue. i/200 will result in int result, where you really want a double. Change it to i/200d

For example...

import java.awt.Dimension;
import java.awt.EventQueue;
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.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

final public class Test {

    private int timeStep = 0;
    private final int ballYTravel = 100;
    private final int BALL_NUM = 24;

    public static void main(String... args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new DrawPanel());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    class DrawPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        public DrawPanel() {
            new Timer(10, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    timeStep++;
                    repaint();
                }
            }).start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 200);
        }

        public double getY(int i, int t) {
            return 100 + ballYTravel / 2 * (Math.sin(t * (i / 200d + 0.08)));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (int k = 0; k < BALL_NUM; k++) {
                g.fillRect(10 + 20 * k, (int) getY(k, timeStep), 6, 6);
            }

        }
    }
}

You're also breaking the paint chain, which is going to cause you issues in the long run, make sure you are calling super.paintComponent...

For more details see...

Upvotes: 5

Related Questions