1

I'm having trouble getting smooth and fluid motion with java Swing. Using this code, which involves using a BufferedImage to draw graphics to before applying it to the panel, gives me results with shaky motion and stuttering. How can I fix this?

public class SmoothMotion extends JPanel {

    public static final int size = 800;
    public static int pos = 0;

    public static void main(String[] args) {
        JPanel panel = new SmoothMotion();
        JFrame frame = new JFrame("Smooth As");
        frame.setSize(size, size);
        frame.add(panel);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Timer timer = new Timer(17, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                SmoothMotion.updateItems();
                panel.repaint();
            }
        });
        timer.start();
    }

    public static void updateItems() {
        pos += 4;
        pos = pos > 750 ? 0 : pos;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, size, size);
        g.setColor(Color.RED);
        g.fillRect(pos > 375 ? 750 - pos : pos, 100, 50, 50);
    }
}

1 Answers1

2
  1. don't override paint(). Custom painting is done by overriding paintComponent(...)

  2. there is no need for the BufferedImage. Swing is double buffered by default. Just invoke super.paintComponent(graphics) first to clear the background and then do your custom painting.

  3. the painting method should NOT change properties of the class. You should have a method like updatePos(…) to update the position.

  4. The ActionLIstener would invoke the updatePos() which would then invoke repaint().

See: get width and height of JPanel outside of the class for an example that demonstrates many of the above suggestions.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thanks. I updated my code to match what you suggested. I also changed the timer interval to be closer to a 60fps refresh rate and increased the position increment accordingly. I still seem to be getting stuttering, though. Is there anything else I can do to get smoother motion? I put the modified code in my original post. – Ethan James Mar 18 '20 at 19:29
  • Don't think you can do any better using Swing. Check out: https://gamedev.stackexchange.com/questions/34090/java2d-game-flickering for some reading material. – camickr Mar 18 '20 at 20:16