问题
Using JavaFX 8.0 and JRE 1.8.0 u45 in IntelliJ, I created a basic pixel editor app. I have two windows(stages). One is a 32x128 matrix of Circle
Objects placed in a Grid Pane
and the other, a Tools widow; I have one Controller.java
. Using the mouse, the Tools window provides tools to draw lines, rectangles, etc. and a menu for Setup, Files and Playlists. The Files menu presents the user with Open, SaveAs and Delete. To view a saved pixel art file, the user clicks Open and via the JFileChooser
, the selected file is opened and each Circle’s assigned color is displayed using the following method:
public static void openFile( String pathName) throws IOException {
path = Paths.get(pathName);
pixelByteArray = Files.readAllBytes(path);
int cnt = 0;
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
String hexRGB = String.format("#%02X%02X%02X",
pixelByteArray[cnt++], //red
pixelByteArray[cnt++], //green
pixelByteArray[cnt++]); //blue
Color color = Color.valueOf(hexRGB);
pixelArray[r][c].setFill(color);
}
}
String fileName = path.getFileName().toString();
window.setTitle(MessageFormat.format("Pixel Array {0} x {1} File: {2}", Integer.toString(row), Integer.toString(col), fileName));
} // openFile
The Circle’s color is updated with for loops using setFill(color).
Next I created a class to test a basic slide show. I would use JFileChooser
to select multiple files, put them in an ArrayList<file>
and use the openFile(pathname)
in a for
loop to display each, pausing 5 secs between each openFile(pathname)
as shown below:
public class PlayPlaylist {
public static void playPlaylist() throws IOException, InterruptedException {
FileChooser fileChooser = new FileChooser();
fileChooser.setInitialDirectory(new File("C:\\ProgramData\\L1 Art Files\\"));
fileChooser.setTitle("Play One or More Pixel Art Files");
java.util.List<File> selectedFiles = fileChooser.showOpenMultipleDialog(null);
for (File selectedFile : selectedFiles) {
openFile(selectedFile.getPath());
sleep(5000);
}
} //Method playPlaylist()
I first used wait(5000)
but couldn’t compile because I have a static method, which I need. The wait()
method won’t run in a static method. I then tried sleep(5000)
which compiles but to my confusion only the last file in the ArrayList<file>
will be displayed. All the pixel art files 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. The for
loop, setFill(color)
process in openFile()
seems to be paused even though the setTitle()
is executed correctly, which is after the setFill(color)
process?
I’m new to Java and JavaFX and have never created any threads directly in this program or any other but researching possible problems implies the problem may be related to threads.
Is there a classic fix to this problem? Thanks for any help
After studying the references and suggested solutions below, I am unable to fix the problem. I tried two code changes. The first was to the for loop
code above:
for (File selectedFile : selectedFiles) {
Platform.runLater(() -> {
try {
openFile(selectedFile.getPath());
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
});
The second change was to the openFile(pathname) above:
final int finalR = r;
final int finalC = c;
Platform.runLater(() -> pixelArray[finalR][finalC].setFill(color));
I get the same results as described above with only the last file being displayed. If I simply select one file in the Arraylist<File>
it will display, i.e.:
if (selectedFiles != null) {
File playFile = selectedFiles.get(0);
openFile(playFile.getPath());
System.out.println("\n File 1 = " + playFile.getPath());
}
Now if I add Sleep(5000)
:
if (selectedFiles != null) {
File playFile = selectedFiles.get(0);
openFile(playFile.getPath());
System.out.println("\n File 1 = " + playFile.getPath());
sleep(5000);
}
It will display the pixel art file after 5 secs. What I don't understand is why it appears to "skip" over the pixelArray[r][c].setFill(color));
which sets all the Circle's to the saved colors but does execute the following and last statement in the openFile(pathname)
which is setTitle(...)
? It's like sleep(5000)
blocks the pixelArray[r][c].setFill(color));
but nothing else?
Why can I openFile(pathname)
for just one file with proper results but not two or more in sequence?
I also have the two UI windows posted on the web at: Virtual Art. I think the pixel art shown in the Pixel Array window clarifies the goal of creating a user-defined slide show.
***This question was answered elegantly by jewelsea at:
How to avoid Thread.sleep() in a for loop from interrupting the UI Thread?***
回答1:
You have two problems here, your understanding of wait()
, and a GUI multithreading issue.
About the GUI multithreading... You will find more informations here about Platform.runLater(...)
:
Platform.runLater and Task in JavaFX
Now about Wait
... It will pause your Thread until a Notify
event is received through its monitor. To be able to call notify() you need to synchronize on the same object (the monitor).
synchronized (someObject) {
someObject.wait();
}
/* different thread / object */
synchronized (someObject) {
someObject.notify();
}
If you want to use Wait
, you will need another Thread (a Timer
?), to wakeup/notify you. Sleep
should work fine in your case, as long as you use Platform.runlater(...)
来源:https://stackoverflow.com/questions/34003813/wait-sleep-not-working-as-thought