在IntelliJ中使用JavaFX 8.0和JRE 1.8.0 u45,我创建了一个基本的像素编辑器应用程序。我有两个窗口(阶段)。一个是放置在Circle
中的Grid Pane
个对象的32x128矩阵,另一个是工具寡妇;我有一个Controller.java
。使用鼠标,“工具”窗口提供绘制线条,矩形等的工具以及“设置”,“文件”和“播放列表”的菜单。 “文件”菜单向用户显示“打开”,“另存为”和“删除”。要查看已保存的像素艺术文件,用户单击“打开”,然后通过JFileChooser
打开所选文件,并使用以下方法显示每个Circle的指定颜色:
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
Circle的颜色使用setFill(颜色)更新for循环。
接下来,我创建了一个类来测试基本幻灯片。我会使用JFileChooser
选择多个文件,将它们放在ArrayList<file>
中并使用openFile(pathname)
循环中的for
来显示每个文件,在每个{{1}之间暂停5秒如下所示:
公共课PlayPlaylist {
openFile(pathname)
我第一次使用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()
但无法编译,因为我有一个静态方法,我需要它。 wait(5000)
方法不会在静态方法中运行。然后我尝试编译了wait()
,但是由于我的困惑,只会显示sleep(5000)
中的最后一个文件。所有像素艺术文件将正确显示ArrayList<file>
并暂停约5秒,但圆圈不会更改为指定的颜色,除了最后一个文件,经过5秒后。 setTitle()
中的for
循环,setFill(color)
进程似乎暂停,即使openFile()
正确执行,即setTitle()
进程之后?
我是Java和JavaFX的新手,并且从未在此程序中直接创建任何线程,但是研究可能的问题意味着问题可能与线程有关。
这个问题有经典的解决方法吗?谢谢你的帮助
在研究了下面的参考资料和建议的解决方案后,我无法解决问题。我尝试了两次代码更改。第一个是上面的setFill(color)
代码:
for loop
第二个变化是上面的openFile(路径名):
for (File selectedFile : selectedFiles) {
Platform.runLater(() -> {
try {
openFile(selectedFile.getPath());
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
});
我得到与上述相同的结果,只显示最后一个文件。如果我只选择final int finalR = r;
final int finalC = c;
Platform.runLater(() -> pixelArray[finalR][finalC].setFill(color));
中的一个文件,它将显示,即:
Arraylist<File>
现在,如果我添加if (selectedFiles != null) {
File playFile = selectedFiles.get(0);
openFile(playFile.getPath());
System.out.println("\n File 1 = " + playFile.getPath());
}
:
Sleep(5000)
5秒后显示像素艺术文件。我不明白为什么它似乎&#34;跳过&#34;在if (selectedFiles != null) {
File playFile = selectedFiles.get(0);
openFile(playFile.getPath());
System.out.println("\n File 1 = " + playFile.getPath());
sleep(5000);
}
上将所有Circle设置为已保存的颜色,但是会在pixelArray[r][c].setFill(color));
openFile(pathname)
中执行以下和最后一个语句吗?它就像setTitle(...)
阻止了sleep(5000)
,但没有别的?
为什么我pixelArray[r][c].setFill(color));
只能获得一个具有正确结果而不是两个或更多顺序的文件?
我还在网络上发布了两个用户界面窗口:Virtual Art。我认为像素阵列窗口中显示的像素艺术阐明了创建用户定义的幻灯片放映的目标。
*** jewelsea在
时优雅地回答了这个问题如何避免for循环中的Thread.sleep()中断UI线程?***
答案 0 :(得分:3)
这里有两个问题,您对wait()
的理解以及GUI多线程问题。
关于GUI多线程...您可以在此处找到有关Platform.runLater(...)
:
Platform.runLater and Task in JavaFX
现在关于Wait
...它将暂停你的线程,直到通过其监视器收到Notify
事件。为了能够调用notify(),您需要在同一对象(监视器)上进行同步。
synchronized (someObject) {
someObject.wait();
}
/* different thread / object */
synchronized (someObject) {
someObject.notify();
}
如果你想使用Wait
,你需要另一个线程(Timer
?)来唤醒/通知你。只要您使用Sleep
Platform.runlater(...)
就可以正常使用