I have a MainController and a UDPServer class that is spinning in a separate thread and waiting for a message when the message arrives, I need to display it on the GUI. How to properly organize such an interaction?

public class UDPServer implements Runnable { // ... @Override public void run() { // ... if(message.equals("N1-M")){ // пришло сообщение и нужно отобразить его в GUI // в моем случае отобразить значит изменить цвет vRectangle } // ... } } public class MainController { // ... @FXML Rectangle vRectangle; // ... } 

    2 answers 2

    The logic is:

     import javafx.application.Platform; public class UDPServer implements Runnable { private MainController mc; public UDPServer(MainController mc){ this.mc = mc; } // ... @Override public void run() { // ... if(message.equals("N1-M")){ // пришло сообщение и нужно отобразить его в GUI // в моем случае отобразить значит изменить цвет vRectangle Platform.runLater(new Runnable() { @Override public void run() { mc.updateColor(Color.BLUE); }); } // ... } } public class MainController { // ... @FXML Rectangle vRectangle; public void updateColor(Color clr) { vRectangle.setColor(clr); } // ... } 

    When creating the UDPServer object in the MainController class, you need to remember to pass a reference to the controller class object.

    For example:

     @Override public void initialize(.....) { new Thread(new UDPServer(this)); } 

    UPDATE

    Wrote an illustrative example (and checked!)

    Main.java

     package example.update.color; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; public class Main extends Application { @Override public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml")); Scene scene = new Scene(root); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } } 

    ChildrenThread.java

     package example.update.color; import static java.lang.Thread.sleep; import java.util.Random; import javafx.application.Platform; import javafx.scene.paint.Color; public class ChildrenThread implements Runnable { private final FXMLDocumentController fxmlCntllr; public ChildrenThread(FXMLDocumentController fxmlCntllr) { this.fxmlCntllr = fxmlCntllr; } @Override public void run() { Random r = new Random(); while (true) { try { sleep(1000); Platform.runLater(new Runnable() { @Override public void run() { fxmlCntllr.updateColor(new Color(r.nextFloat(), r.nextFloat(), r.nextFloat(), 1)); } }); } catch (InterruptedException ex) { } } } } 

    FXMLDocument.fxml

      <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.shape.*?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="example.update.color.FXMLDocumentController"> <children> <Rectangle fx:id="vRectangle" arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE" height="171.0" layoutX="60.0" layoutY="15.0" stroke="BLACK" strokeType="INSIDE" width="200.0" /> </children> </AnchorPane> 

    FXMLDocumentController.java

     package example.update.color; import java.net.URL; import java.util.ResourceBundle; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; public class FXMLDocumentController implements Initializable { @FXML private Rectangle vRectangle; @Override public void initialize(URL url, ResourceBundle rb) { new Thread(new ChildrenThread(this)).start(); } void updateColor(Color clr) { vRectangle.setFill(clr); } } 
    • Thank you very much for the answer. But I could not get the code to work. Exception in thread "pool-2-thread-1" is thrown java.lang.IllegalStateException: Not on FX application thread; currentThread = pool-2-thread-1 - AlexeyChizhov
    • @AlexeyChizhov, supplemented the answer ... The code is 100% working. PS Before that, I still managed to draft a version of data exchange between threads without JavaFX. Goo.gl/mq1rbT - Sergey Sereda
    • Thanks again big. I created a new project, completely copied all the code, but when I run, I still have Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4 - AlexeyChizhov
    • one
      Try instead of new Thread(new ChildrenThread(this)).start(); write Platform.runLater(new ChildrenThread(this)); - Sergey Sereda
    • one
      Very strange, but on a home computer, a project that did not work at work works fine, without any changes. It seems everything is the same, everywhere the latest versions and all that. Strange. Platform.runLater earned if done like this: Platform.runLater (new Runnable () {@Override public void run () {fxmlCntllr.updateColor (new Color (r.nextFloat (), r.nextFloat (), r.nextFloat (), one)); } }); - AlexeyChizhov

    I don’t know the exact answer as an idea:

    1. Create a global variable of the volatile type (atomic is said to be similar)
    2. Write a listener - when changing the value of a variable, do something ...