0

I'm having a problem I'm making a pool game and I need the ballos to react when I simulate a hit, the program works like this, you click the direction and power to hit the ball and the click go, the go button is in the GUI class where my labels are created, the button calls a method from my main class that recieves the parameter and then with a while in it, changes the X and Y of the ball till the power is reduced to 0 and then stops, the code is working, but the ball moves until the while stops. So the while works and when the power int is 0 the while goes out and then the new X,Y are painted.

This is the funcion that the button calls, the button sends all the parameters

 public void golpe(int pbola, int pvelocidad, String pdireccion, JLabel[] listalabels) throws InterruptedException{

    listabolas[pbola].setVelocidad(pvelocidad);
    listabolas[pbola].setDireccion(pdireccion);

    while (listabolas[pbola].getVelocidad() > 0) {

        moverBola(pbola, listalabels);

        //System.out.println(listabolas[pbola].getPosX());
        //System.out.println(listabolas[pbola].getPosY());

        Thread.sleep(500);

        //This line is supposed to change the X and Y of the object over and over
        //but only does it till the end
        listalabels[pbola].setLocation(listabolas[pbola].getPosX(), listabolas[pbola].getPosY());
    }

}

Here is the function moverbola(), only copied one "if" so that the code doesn't look to big

private void moverBola(int pbola, JLabel[] listalabels) {

    if (listabolas[pbola].getDireccion().equals("SE")) {

        int pposX = listabolas[pbola].getPosX();
        listabolas[pbola].setPosX(pposX + 1);


        int pposY = listabolas[pbola].getPosY();
        listabolas[pbola].setPosY(pposY + 1);


    }
Santiago VdeK
  • 72
  • 2
  • 13

1 Answers1

1

Swing is a single threaded framework. That is, all interactions with UI are expected to occur from within a single thread, known as the Event Dispatching Thread.

Any action that blocks this thread, will prevent the EDT from updating the screen or processing any new events.

Your while-loop is blocking the EDT, preventing it from painting any updates until after the while-loop is completed.

Take a look at Concurrency in Swing for more details.

There are a number of approaches you could take...

You could use a Thread, but this causes problems as you need to ensure that any changes you make to the UI are re-synced back to the EDT and this can become messy...

For example

You could use a javax.swing.Timer that ticks at a regular interval and you would update any internal parameters from within it's assigned ActionListener. Because the tick events occur within the EDT, it is save to update the screen from within it.

For example

You could use a SwingWorker to run the task in the background. It has methods for re-syncing updates back to the EDT, but might be a little over kill for your purposes...

Updated with a possible Timer example

Caveat- It is very hard to produce a reasonable example with only a code snippet, but, something like this might work

public void golpe(final int pbola, int pvelocidad, String pdireccion, final JLabel[] listalabels) throws InterruptedException{

    listabolas[pbola].setVelocidad(pvelocidad);
    listabolas[pbola].setDireccion(pdireccion);

    Timer timer = new Timer(40, new ActionListener() {
        public void actionPerformed(ActionEvent evt) {

            if (listabolas[pbola].getVelocidad() == 0) {
                ((Timer)evt.getSource()).stop();
            } else {            
                moverBola(pbola, listalabels);
            }

        }
    });
    timer.setRepeats(true);
    timer.start();

}
Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Ok and where should I implement for example the javax.swing.Timer? In the while and remove the thread.sleep(), don;t you have an idea? – Santiago VdeK Aug 13 '13 at 06:09
  • I have lots of ideas, you probably just won't like them ;) - Yes. I would remove the `Thread.sleep` statement. I would remove the `while-loop` and replace it with a `Timer`. I would also disable the button that is calling this method. I would place all you parameters into some kind of object that the `ActionListener` of the `Timer` can access and until the power goes to 0, let the Timer ticking – MadProgrammer Aug 13 '13 at 06:10
  • So, first remove the Thread.sleep and the while, replace them with a timer and the button GO! button instead of sending those parameter it would activate a timer that will run until the ball power hits 0, and that would keep my GUI updated and refreshed? Could you give me some kind of example of how to make this timer and relate it to the action listener of the GUI class? – Santiago VdeK Aug 13 '13 at 06:19
  • I though I did? Did you see the updates or am I missing something? – MadProgrammer Aug 13 '13 at 06:23
  • No, I get the idea perfectly but I'm new in java and I haven't found a similar code to try to pass it to mine :/ – Santiago VdeK Aug 13 '13 at 06:26
  • Okay. Have you tried using the example above? What issues do you have with it? – MadProgrammer Aug 13 '13 at 06:29
  • Ok, I'm almost sure that will work I'll just try to modify to make it work, Thank you very very much. Could I send you a PM in case of something else? – Santiago VdeK Aug 13 '13 at 06:33
  • Dude, I almost died when it worked just missed a line, Incredible you made my night! Thank you very very much! – Santiago VdeK Aug 13 '13 at 06:41
  • Wow, that's makes a nice change :P – MadProgrammer Aug 13 '13 at 06:42
  • Personally, I always get suspicious over code that works right first time, when you just know it's suppose to break... – MadProgrammer Aug 13 '13 at 06:52