How to avoid Thread.sleep() in a for loop from int

2019-09-21 00:17发布

I have the following pseudo code to clarify my problem and a solution. My original posting and detailed results are on Stack Overflow at: Wait() & Sleep() Not Working As Thought.

public class PixelArtSlideShow {  // called with click of Menu item.

   create List<File>  of each selected pixelArtFile
   for (File pixelArtFile : List<File>) {
      call displayFiles(pixelArtFile);
      TimeUnits.SECONDS.sleep(5); }
   }

    public static void displayFiles(File pixelArtFile) {

       for (loop array rows)
          for (loop array columns)
             read-in sRGB for each pixel - Circle Object
             window.setTitle(....)
}

// when above code is used to Open a pixelArtFile, it will appear instantly in  a 32 x 64 array

PROBLEM: As detailed extensively on the other post. Each pixelArtFile will display the setTitle() correctly and pause for about 5 secs but the Circle’s will not change to the assigned color except for the last file, after the 5 secs have passed. It's like all the code in the TimeUnits.SECONDS.sleep(5); are skipped EXCEPT the window.setTitle(...)?

My understanding is the TimeUnits.SECONDS.sleep(5); interrupts the UI Thread uncontrollable and I guess must somehow be isolated to allow the displayFiles(File pixelArtFile) to fully execute.

Could you please show me the most straight forward way to solve this problem using the pseudo code for a more completed solution?

I have tried Runnables, Platform.runLater(), FutureTask<Void>, etc. and I'm pretty confused as to how they are meant to work and exactly coded.

I also have the two UI windows posted on the web at: Virtual Art. I think the pixelArtFile shown in the Pixel Array window may clarify the problem.

THANKS

1条回答
Viruses.
2楼-- · 2019-09-21 01:01

Don't sleep the UI thread. A Timeline will probably do what you want.

List<File> files;
int curFileIdx = 0;

// prereq, files have been appropriately populated.
public void runAnimation() {
    Timeline timeline = new Timeline(
            new KeyFrame(Duration.seconds(5), event -> {
                if (!files.isEmpty()) {
                    displayFile(curFileIdx);
                    curFileIdx = (curFileIdx + 1) % files.size();
                }
            })
    );
    timeline.setCycleCount(Timeline.INDEFINITE);
    timeline.play();
}

// prereq, files have been appropriately populated.
public void displayFile(int idx) {
    File fileToDisplay = files.get(idx);
    // do your display logic.
}

Note, in addition to the above, you probably want to run a separate task to read the file data into memory, and just have a List<ModelData> where ModelData is some class for data you have read from a file. That way you wouldn't be continuously running IO in your animation loop. For a five second per frame animation, it probably doesn't matter much. But, for a more frequent animation, such optimizations are very important.

查看更多
登录 后发表回答