Dries Coppens
Dries Coppens

Reputation: 1085

JavaFX ListView

I have a ListView<String> list. I can easily get the next item in the ListView with a button using this code:

 public void toNext(){
    list.getSelectionModel().selectNext();
 }

But if I want to go through the ListView automatically with a button, it won't work. I tried the following code:

 public void play(){
    try {
        for (int i = 0; i < list.getItems().size() ; i++) {
            list.getSelectionModel().select(i);
            Thread.sleep(500);
        }
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
 }

This code doesn't select the different strings in the list but just skips to the last string after the given waittime. How can I get it to select each string in the list with a delay of 500 ms?

Upvotes: 0

Views: 221

Answers (3)

James_D
James_D

Reputation: 209340

Consider using an animation:

Timeline animation = new Timeline(
    new KeyFrame(Duration.millis(500), e -> list.getSelectionModel().selectNext()));
list.getSelectionModel().select(0);
animation.setCycleCount(list.getItems().size()-1);
animation.play();

Advantages to this approach include

  1. It is lightweight, and doesn't involve creating a new thread of execution. It simply hooks into the existing FX Application Thread and pulse mechanism.
  2. The code is cleaner.
  3. It has additional built-in API, so it is much easier to stop or pause the animation than it would be if you created a new thread to manage this.

Upvotes: 3

Ben
Ben

Reputation: 3518

The problem is, your loop completely runs in FxApplicationThread.
So, the UI won't update during the loop.

Better would be something like:

public void play(){
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < lijst.getItems().size(); i++) {
                final int idx = i;
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        lijst.getSelectionModel().select(idx);
                    }
                });
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

            }
        }
    });
    t.start();
}

Upvotes: 3

hotzst
hotzst

Reputation: 7496

You have to wrap the call that makes the UI update in the UI thread otherwise all the updates are done in one bunch at the end, hence it jumps to the end of the list.

 public void play(){
    try {
        for (int i = 0; i < list.getItems().size() ; i++) {
            final int index = i;
            Platform.runLater(() -> {
                list.getSelectionModel().select(index)
            });
            Thread.sleep(500);
        }
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
 }

Upvotes: 0

Related Questions