JAVAFX:为什么等待游标需要一个新线程?

JAVAFX : why wait cursor needs a new thread?

我会明白为什么

 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. 将我的光标设置为等待(它进入 GUI 队列)
  2. 做我的长任务...(它进入 GUI 队列,但我预计光标会改变,在队列中,它在此之前执行)
  3. 将我的光标重置为默认值(在我的任务完成后)

所以,我的长任务没有进入 MAIN 队列?因为,如果它进入主队列,我希望它在我的 WAIT 游标首先插入队列之后执行。 为什么会出现这种行为?

没有线程,您的代码将在 FX 应用程序线程上执行。这是(有效地)负责将 UI 渲染到屏幕并处理用户输入的线程。如果您在此线程上执行一个 long-运行 任务,那么在您的 long-运行 任务完成之前,您将阻止 FX 应用程序线程的任何正常功能发生。特别是,如果你这样做

scene.setCursor(Cursor.WAIT);
longRunningTask();
scene.setCursor(Cursor.DEFAULT);

然后设置将按照您指定的顺序进行,但是在所有代码行完成之前场景不会重新渲染。因此,在您的代码完成之前,您永远不会真正看到对 UI 的任何更改 - 包括对光标的更改。下次 FX 应用程序线程有机会渲染场景时,光标设置为 Cursor.DEFAULT,您永远不会看到等待光标。

多线程和 JavaFX 有两条基本规则(同样的规则通常适用于大多数 UI 工具包):

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

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

  1. 在 FX 应用程序线程上将光标设置为 WAIT
  2. 在后台线程上开始您的长 运行 任务
  3. 任务完成后,将光标设置回 FX 应用程序线程上的 DEFAULT

您可以使用 Task:

scene.setCursor(Cursor.WAIT);
Task<Void> task = new Task<Void>() {
    @Override
    public Void call() {
        // long running task here...
        return null ;
    }
};
task.setOnSucceeded(e -> scene.setCursor(Cursor.DEFAULT));
new Thread(task).start();