Search code examples
javaswingactionlistenerpaintcomponent

Drawing not being repainted


I want to move a ball along the x-axis to either the right or the left, depending on which JButton the user clicks. The ball is not moving when either of the JButtons is clicked.

I have used System.out.println() to try and find out what is wrong and the program is detecting clicks on the JButtons and changes the variable (int horizontal) which has to be changed to move the ball as well.

MoveBallPanel class:

package test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class MoveBallPanel extends JPanel implements ActionListener {

// declarations

private JButton moveLeft;
private JButton moveRight;
private int center;
private int horizontal;

public MoveBallPanel() {

    // make elements

    moveLeft = new JButton("To the left");
    moveLeft.addActionListener(this);
    moveRight = new JButton("To the right");
    moveRight.addActionListener(this);

    // add to panel

    add(moveLeft);
    add(moveRight);
}

// to do when JButton is clicked

@Override
public void actionPerformed(ActionEvent e) {

    final int MOVE = 50;

    if (e.getSource() == moveLeft) {
        horizontal -= MOVE;
        // System.out.println("moveLeft JButton has been clicked");
        // System.out.println(horizontal);
    } else {
        horizontal += MOVE;
        // System.out.println("moveRight button has been clicked");
        // System.out.println(horizontal);

    }
    repaint();
}

// draw ball

@Override
public void paintComponent(Graphics g) {

    final int DIAMETER = 100;
    final int VERTICAL = (getHeight() / 2) - (DIAMETER / 2);

    center = getWidth() / 2;
    horizontal = center - DIAMETER / 2;

    super.paintComponents(g);
    g.setColor(Color.ORANGE);
    g.fillOval(horizontal, VERTICAL, DIAMETER, DIAMETER); 
    g.setColor(Color.BLACK);
    g.drawOval(horizontal, VERTICAL, DIAMETER, DIAMETER);
    g.drawOval(horizontal + DIAMETER / 4, VERTICAL, DIAMETER / 2, DIAMETER);

    }

}

MoveBall class:

package test;

import javax.swing.*;

public class MoveBall extends JFrame {

public MoveBall() {

    // JFrame object

    JFrame frame = new JFrame();

    // JFrame properties

    frame.setSize(500, 500);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setTitle("Move ball");
    frame.add(new MoveBallPanel());
    frame.setVisible(true);

}

    public static void main(String[] args) {
        new MoveBall();
    }

}

Solution

  • Look at your two pieces of code...

    @Override
    public void actionPerformed(ActionEvent e) {
        final int MOVE = 50;
        if (e.getSource() == moveLeft) {
            horizontal -= MOVE;
        } else {
            horizontal += MOVE;
    
        }
        repaint();
    }
    

    In your actionPerformed method, you are updating the horizontal value, that sounds reasonable, but in your paintComponent method you are reassigning the value with something else, overriding what ever the actionPerformed method did...

    public void paintComponent(Graphics g) {
        //...
        horizontal = center - DIAMETER / 2;
        //...
    }
    

    Start by taking a look at Performing Custom Painting and Painting in AWT and Swing to understand how painting works in Swing.

    What you need to do is create some kind of flag which can be used to tell the paintComponent method to initialise the horizontal to a default position, once, then let the program update the value from there...