-3

I know there are many questions out there regarding action listeners etc. However, none can help me with my specific issue...no matter which way I try to do it I always get an error. Here is my simple bouncing ball program:

public class ControlledBall extends JPanel implements Runnable {

    int diameter;
    long delay;
    private int x;
    private int y;
    private int vx;
    private int vy;

    public ControlledBall(int xvelocity, int yvelocity) {


        diameter = 30;
        delay = 40;
        x = 1;
        y = 1;
        vx = xvelocity;
        vy = yvelocity;
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g.setColor(Color.blue);
        g.fillOval(x,y,30,30);
        g.setColor(Color.black);
        g2.drawOval(x,y,30,30); //draw
    }

    public void run() {
        while(isVisible()) {
            try {
                Thread.sleep(delay);
            } catch(InterruptedException e) {
                System.out.println("Something Went Wrong!");
            }
            move();
            repaint();
        }
    }

    public void move() {
        if(x + vx < 0 || x + diameter + vx > getWidth()) {
            vx *= -1;
        }
        if(y + vy < 0 || y + diameter + vy > getHeight()) {
            vy *= -1;
        }
        x += vx;
        y += vy;

    }

    public void stop(){
        x=0;
        y=0;
    }

    public class Action implements ActionListener{
        public void actionPerformed(ActionEvent e){
            stop();
        }
    }



    public static void main(String[] args) {
        ControlledBall ball2 = new ControlledBall(12,2);
        JFrame window = new JFrame("Controlled Ball");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        window.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        JButton stop = new JButton("Stop");
        stop.setSize(4,400);
        stop.setVisible(true);
        stop.setText("Stop");
 //       stop.addActionListener(new Action());

        stop.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

           }
        });

        window.add(stop);
        JButton start = new JButton("Start");
        start.setSize(100,100);
        start.setVisible(true);
        start.setText("Start");
        window.add(start);
        start.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

            }
        });


        c.ipadx = 400;
        c.ipady = 400;
        c.gridx = 10;
        c.gridy = 10;
        window.add(ball2,c);
       c.ipadx = 50;
      c.ipady = 20;
       c.gridx = 10;
       c.gridy = 10;

        window.pack();
        window.setSize(600,600);
        window.setLocation(250,200);
        window.setVisible(true);


        new Thread(ball2).start();
    }
}

as you can see by the commented bits I've tried a few different techniques and none have worked. any advice would be greatly appreciated. Thanks

The main error I get is:

non static field cannot be referenced from a static context

and I assume that's because I'm running it from the main method.

t4nhpt
  • 5,264
  • 4
  • 34
  • 43
Javanewbie
  • 39
  • 8

1 Answers1

2

The first thing you really want to do is get rid of your run method (and your reliance on Runnable). This is really an inappropriate way to perform regular updates in Swing.

Swing is single threaded and NOT thread safe, your current approach risks dirty read/writes across thread boundaries.

Instead, you want to use a Swing Timer, see How to Use Swing Timers for more details.

The next thing you want to do is add a start method and update the stop method to support the use of a Swing Timer...

public class ControlledBall extends JPanel {

    //...

    private Timer timer;

    public void stop() {
        if (timer == null) {
            return;
        }
        timer.stop();
        timer = null;
        x = 0;
        y = 0;
    }

    public void start() {
        if (timer != null) {
            return;
        }
        timer = new Timer(delay, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                move();
                repaint();
            }
        });
        timer.start();
    }

Then, your start and stop buttons just need to be updated to call these methods...

    stop.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            ball2.stop();
        }
    });
    //...
    start.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            ball2.start();
        }
    });
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366