JAVAFX:为什么等待游标需要一个新线程?
我明白为什么
scene.setCursor(Cursor.WAIT); long task... scene.setCursor(Cursor.DEFAULT);
需要新线程; 它适用于:
private void set_cursore_attesa(final Scene scene) { Runnable r=new Runnable() { @Override public void run() { scene.setCursor(Cursor.WAIT); } }; Thread t=new Thread(r); t.start(); } private void set_cursore_normale(final Scene scene) { Runnable r=new Runnable() { @Override public void run() { scene.setCursor(Cursor.DEFAULT); } }; Thread t=new Thread(r); t.start(); } in my function: set_cursore_attesa(scene); long task... set_cursore_normale(scene);
为什么我不能使用相同的线程? 一世:
- 将我的光标设置为WAIT(它进入GUI队列)
- 做我的长任务…(它进入GUI队列,但我期望光标改变,即在队列中,它在此之前执行)
- 将我的光标重置为DEFAULT(在我的任务完成后)
那么,我的长期任务不会进入MAIN队列? 因为,如果它进入主队列,我预计它会在我首先插入队列的WAIT游标之后执行。 为什么会这样?
如果没有线程,您的代码将在FX Application Thread上执行。 这是(有效地)负责将UI呈现给屏幕并处理用户输入的线程。 如果在此线程上执行长时间运行的任务,则会阻止FX应用程序线程的任何正常function发生,直到长时间运行的任务完成。 特别是,如果你这样做
scene.setCursor(Cursor.WAIT); longRunningTask(); scene.setCursor(Cursor.DEFAULT);
然后设置按照您指定的顺序进行, 但在完成所有代码行之前,场景不会被重新呈现 。 因此,在代码完成之前,您永远不会看到UI的任何更改 – 包括对光标的更改。 下一次FX应用程序线程有机会渲染场景时,光标设置为Cursor.DEFAULT
,您永远不会看到等待光标。
multithreading和JavaFX有两个基本规则(相同的规则通常适用于大多数UI工具包):
- 必须在FX应用程序线程上执行对UI的任何更改
- 不应在FX应用程序线程上执行长时间运行的进程(因为它们使UI无响应)
所以你的解决方案实际上并不正确,因为你违反了这两个规则。 你应该
- 在FX应用程序线程上将光标设置为
WAIT
- 在后台线程上启动长时间运行的任务
- 任务完成后,在FX应用程序线程上将光标设置回
DEFAULT
。
您可以使用Task
执行此操作:
scene.setCursor(Cursor.WAIT); Task task = new Task () { @Override public Void call() { // long running task here... return null ; } }; task.setOnSucceeded(e -> scene.setCursor(Cursor.DEFAULT)); new Thread(task).start();