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); 

为什么我不能使用相同的线程? 一世:

  1. 将我的光标设置为WAIT(它进入GUI队列)
  2. 做我的长任务…(它进入GUI队列,但我期望光标改变,即在队列中,它在此之前执行)
  3. 将我的光标重置为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工具包):

  1. 必须在FX应用程序线程上执行对UI的任何更改
  2. 不应在FX应用程序线程上执行长时间运行的进程(因为它们使UI无响应)

所以你的解决方案实际上并不正确,因为你违反了这两个规则。 你应该

  1. 在FX应用程序线程上将光标设置为WAIT
  2. 在后台线程上启动长时间运行的任务
  3. 任务完成后,在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();