有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

那么,我的长任务不在主队列中?因为,若它进入主队列,我希望它在我的等待游标(首先插入队列)之后执行。 为什么会有这种行为


共 (1) 个答案

  1. # 1 楼答案

    如果没有线程,代码将在FX应用程序线程上执行。这是一个线程,它(有效地)负责将UI呈现到屏幕上并处理用户输入。如果在此线程上执行长时间运行的任务,则在长时间运行的任务完成之前,将阻止FX应用程序线程的任何正常功能。特别是,如果你

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

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

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

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

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

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

    您可以使用^{}执行此操作:

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