Question

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);


    }
Was it helpful?

Solution

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();

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top