问题描述
在IntelliJ中使用JavaFX 8.0和JRE 1.8.0 u45,我创建了一个基本的像素编辑器应用程序.我有两个窗户(舞台).一个是放置在Grid Pane
中的Circle
对象的32x128矩阵,另一个是工具寡妇.我有一个Controller.java
.使用鼠标,工具"窗口提供绘制线条,矩形等的工具,以及用于设置",文件"和播放列表"的菜单. 文件"菜单向用户显示打开",另存为"和删除".要查看保存的像素艺术文件,用户单击打开",然后通过JFileChooser
打开所选文件,并使用以下方法显示每个Circle的指定颜色:
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
使用setFill(color)使用for循环更新Circle的颜色.
The Circle’s color is updated with for loops using setFill(color).
接下来,我创建了一个类来测试基本的幻灯片放映.我将使用JFileChooser
选择多个文件,将它们放在ArrayList<file>
中,并在for
循环中使用openFile(pathname)
来显示每个文件,每个openFile(pathname)
之间暂停5秒,如下所示:
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:
公共类PlayPlaylist {
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()
我第一次使用wait(5000)
,但是由于我有一个需要的静态方法而无法编译. wait()
方法不会以静态方法运行.然后,我尝试了sleep(5000)
进行编译,但令我感到困惑的是,只会显示ArrayList<file>
中的最后一个文件.所有像素图文件将正确显示setTitle()
并暂停约5秒钟,但经过5秒钟后,除了最后一个文件外,Circle的颜色不会更改为指定的颜色. for
循环,openFile()
中的setFill(color)
进程似乎已暂停,即使setTitle()
正确执行了(在setFill(color)
进程之后)?
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?
我是Java和JavaFX的新手,从未在此程序或任何其他程序中直接创建任何线程,但是研究可能的问题意味着该问题可能与线程有关.
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
研究完下面的参考文献和建议的解决方案后,我无法解决问题.我尝试了两次代码更改.首先是上面的for loop
代码:
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();
}
});
第二个更改是对上面的openFile(pathname):
The second change was to the openFile(pathname) above:
final int finalR = r;
final int finalC = c;
Platform.runLater(() -> pixelArray[finalR][finalC].setFill(color));
我得到的结果与上述相同,只显示了最后一个文件.如果我只是在Arraylist<File>
中选择一个文件,它将显示,即:
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());
}
现在,如果我添加Sleep(5000)
:
if (selectedFiles != null) {
File playFile = selectedFiles.get(0);
openFile(playFile.getPath());
System.out.println("\n File 1 = " + playFile.getPath());
sleep(5000);
}
它将在5秒钟后显示像素图文件.我不明白的是为什么它似乎会跳过" pixelArray[r][c].setFill(color));
,从而将所有Circle设置为已保存的颜色,但是会在openFile(pathname)
(即setTitle(...)
)中执行以下和最后一条语句?就像sleep(5000)
阻止了pixelArray[r][c].setFill(color));
一样,但是没有别的吗?
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?
为什么我只能按openFile(pathname)
的一个文件获得正确的结果,却不能依次搜索两个或多个?
Why can I openFile(pathname)
for just one file with proper results but not two or more in sequence?
我还在Web上发布了两个UI窗口:虚拟艺术.我认为,像素阵列"窗口中显示的像素图可以阐明创建用户定义的幻灯片放映的目标.
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.
*** Jewelsea在以下位置优雅地回答了这个问题:
***This question was answered elegantly by jewelsea at:
如何避免for循环中的Thread.sleep()中断UI线程?***
How to avoid Thread.sleep() in a for loop from interrupting the UI Thread?***
推荐答案
您在这里遇到两个问题,即对wait()
的理解和GUI多线程问题.
You have two problems here, your understanding of wait()
, and a GUI multithreading issue.
关于GUI多线程...您将在这里找到有关Platform.runLater(...)
的更多信息:
About the GUI multithreading... You will find more informations here about Platform.runLater(...)
:
JavaFX中的Platform.runLater和Task
现在大约Wait
......它将暂停您的线程,直到通过其监视器接收到Notify
事件为止.为了能够调用notify(),您需要在同一对象(监视器)上进行同步.
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();
}
如果要使用Wait
,则需要另一个线程(一个Timer
?)来唤醒/通知您.只要您使用Platform.runlater(...)
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(...)
这篇关于Wait()& Sleep()不能按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!