-1

I'm trying to create a PacMan game, but I'm trying to use platform.runLater() to implement multithreading and the GUI's not updating, even though I've checked that the code itself is running. Here's the pertinent code:

This is the block of code that starts the Platform.runLater() thread.

private void startTimer() {
        this.timer = new java.util.Timer();
        TimerTask timerTask = new TimerTask() {
            public void run() {
                Platform.runLater(new Runnable() {
                    public void run() {
                        update();
                        
                    }
                });
            }
        };
        long frameTimeInMilliseconds = (long)(1000.0 / FRAMES_PER_SECOND);
        this.timer.schedule(timerTask, 0, frameTimeInMilliseconds);
    }


private void update() {
        view.update(this.modelo);   
    }

And this is the block of code that it is running.

    public void update(Model gc) {
        updateMap(gc);
    }
//Sets the image on the already initialized imageviews (not updating gui for some reason)   
private void updateMap(Model gc) {
    for(int i = 0; i < rowCount; i++) {
        for(int j = 0; j < columnCount; j++) {
            char valor = gc.getCelulas(i, j);
            if(valor == 'E' || valor == 'W') {
                visaoMapa[i][j].setImage(imgsMapaVazio[i][j]);          
            }
            else {
                if(valor == 'S')
                visaoMapa[i][j].setImage(imgsMapaCheio[i][j]);
            }
        }
    }
    
}

Update #1 Following James_D's recommendation, I tried changing the startTimer method into this:

private void startTimer() {
        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                update();
            }
        };
        timer.start();
    }

However, the issue still persists.

1 Answers1

-2

If the loop in updateMap() is taking too long to finish while having to run UI updates only on few indexes, then that could be your culprit, because you're still running updateMap() on the UI thread through Platform.runLater()

Try calling update() outside the UI thread :

private void startTimer() {
    this.timer = new java.util.Timer();
    TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            update();
        }
    };
    long frameTimeInMilliseconds = (long) (1000.0 / FRAMES_PER_SECOND);
    this.timer.schedule(timerTask, 0, frameTimeInMilliseconds);
}

Then using Platform.runLater() to execute UI updates inside the loop :

private void updateMap(Model gc) {
    for (int i = 0; i < rowCount; i++) {
        for (int j = 0; j < columnCount; j++) {
            final int fi = i;
            final int fj = j;
            char valor = gc.getCelulas(i, j);
            if (valor == 'E' || valor == 'W') {
                Platform.runLater(() -> visaoMapa[fi][fj].setImage(imgsMapaVazio[fi][fj]));
            } else if (valor == 'S') {
                Platform.runLater(() -> visaoMapa[fi][fj].setImage(imgsMapaCheio[fi][fj]));
            }
        }
    }
}

Note that the code portions you posted can't be used to reproduce the issue because some types are missing so I can't test this solution.

SDIDSA
  • 894
  • 10
  • 19
  • 2
    This is going to flood the runnable queue with potentially hundreds of runnable items to run later every pulse (depends on the size of the map), which may work out ok, but may not. – jewelsea Jan 27 '22 at 04:03
  • I see, I would add short pauses between UI updates to allow the ui to update but I realized the task will run every frame, I think that's a lot of work to do on a per-frame basis. – SDIDSA Jan 27 '22 at 13:19