Method of updating UI with javafx

  • 2021-10-24 23:08:01
  • OfStack

Update UI with javafx

JavaFx If UI is updated in a child thread, either task or runable will report an error

java.lang.IllegalStateException: Not on FX application thread; currentThread =

In this case, you can use the following methods

1. Platform. runLater ()

This method can be called directly in threads whose current thread is not javafx, such as runnable and thread. runLater () is not thread blocking, and it will only be executed when the main thread of javafx is completely empty or idle.


Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            // Update JavaFX The code of the main thread of is placed here 
                            p.cancelProgressBar();
                        }
                    });

But what if you have to execute this code first, there are ways

1. future is a worker thread

It allows you to block the current thread, execute the code in the thread, and execute it sequentially after getting the return value


//  Definition 1 A FutureTask , and then  Plateform.runLater()  This futuretask
                        final FutureTask<String> query = new FutureTask<String>(new Callable<String>() {
                            @Override
                            public String call() throws Exception {
                                    //  New 1 Windows ( Method creates the stage)
                                    VcodeController vc = new VcodeController();
                                    return vc.show(url4vcode);
                            }
                        });
 
                        Platform.runLater(query);       //  Focus  
                        String vcode = query.get();     //  So you can get the return value  
                        System.out.println(vcode);

2. Using CountDownLatch, directly block the current main thread and execute relevant code business


/**
 * Runs the specified {@link Runnable} on the
 * JavaFX application thread and waits for completion.
 *
 * @param action the {@link Runnable} to run
 * @throws NullPointerException if {@code action} is {@code null}
 */
public static void runAndWait(Runnable action) {
    if (action == null)
        throw new NullPointerException("action");
 
    // run synchronously on JavaFX thread
    if (Platform.isFxApplicationThread()) {
        action.run();
        return;
    }
 
    // queue on JavaFX thread and wait for completion
    final CountDownLatch doneLatch = new CountDownLatch(1);
    Platform.runLater(() -> {
        try {
            action.run();
        } finally {
            doneLatch.countDown();
        }
    });
 
    try {
        doneLatch.await();
    } catch (InterruptedException e) {
        // ignore exception
    }
}

3. Use the return value of the task thread

task is an ui thread implemented by javafx, and it implements futureTask and worlker threads, so it can be used as a normal thread, and it can also rewrite the return value method to refresh the interface of ui

However, it should be noted that the call method of task is still a common thread method. If you want to refresh the ui interface in task, you should

scheduled (), succeeded (), running () any one of the methods, it is OK, so that the thread of task, refresh the interface function


package com.yz.readismqtest1; 
import javafx.concurrent.Task; 
public class deda {
    public static void main(String[] args) {
        Task task = new Task() {
            @Override
            protected Object call() throws Exception {
                // Execute common methods 
                return null;
            }
 
            @Override
            protected void scheduled() {
                // Update JavaFX The code of the main thread of is placed here 
                super.scheduled();
            } 
 
            @Override
            protected void succeeded() {
                // Update JavaFX The code of the main thread of is placed here 
                super.succeeded();
            }
 
            @Override
            protected void running() {
                // Update JavaFX The code of the main thread of is placed here 
                super.running();
            }
        }; 
    }
}

Concurrent Programming of JavaFX and Updating of UI

JavaFX Concurrent Programming and UI Update

Project requirements

According to the needs of the project, the concurrent test of the equipment should be carried out, and the test results should be displayed in real time on the interface

Technologies involved

1. Using Observer to realize communication between multiple objects (observer mode)

2. Because there is only one UI, which needs to receive and display a large amount of data in a short time, javafx. concurrent is used

3. Thread pool pool to reduce the resource occupation of objects

The use of the above technology refers to a large number of network resources and books, and will not be listed again. Thank you for your authors.

Core code


// 1 Getting objects from the thread pool 
 ObjectPoolDrawUIService objPool = ObjectPoolDrawUIService.getInstance();
 DrawUIService obj = (DrawUIService)objPool.getObject();
 
 // 2 The initialization of an object    produceCaseResult Is the data content that needs to be updated   ,i It's line number information, which is placed in Object[] Transfer in 
 obj.init(new Object[]{produceCaseResult,i}, new EventHandler<WorkerStateEvent>() {
  @Override
  public void handle(WorkerStateEvent t) {
   Object[] objArray = (Object[])t.getSource().getValue();
   testDetailList.set((int) objArray[1], (ProduceCaseResult)objArray[0]);
   // 4 Because it is executed in a thread, the  returnObject Code cannot follow obj.restart Later, it will lead to being quickly restart
   objPool.returnObject(obj);
  }
 });
 
 // 3 , execution 
 obj.restart();  //  Because it is from pool Gets from, may have finished executing, so restart
 Special attention should be paid to the above code, and the code 4 The following code is the location of javafx.concurrent Core code of 
public class DrawUIService extends Service<Object[]>{
 Object[] showData = {null,null};
 public void init(Object[] showData, EventHandler<WorkerStateEvent> eventHandler) {
  this.showData = showData;
  setOnSucceeded(eventHandler);
 }
 @Override
 protected Task<Object[]> createTask() {
  return new Task<Object[]>() {
   @Override
   protected Object[] call() throws Exception {
    return showData;
   }
  };
 }
}

Related articles: