Update JavaFX scene graph from a Thread

泪湿孤枕 提交于 2020-01-03 04:24:50

问题


I need to update my GUI based on client input. Calling my controller class method, from the background task works. But it can't update the GUI, because it is not the JavaFX application thread..please help.

I tried many of the related Q & A, but I am still confused.

Should I use Platform. runLater or Task ?

Here's my class where I create an instance of controller class

public class FactoryClass {

    public static Controller_Gui1 createGUI() {
        FXMLLoader fxLoader = new FXMLLoader();
        fxLoader.setLocation(MainApp_Gui1.class.getResource("/com/Gui_1.fxml"));
        AnchorPane anchorPane = null;
        try {
            anchorPane = (AnchorPane) fxLoader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Controller_Gui1 controller_Gui1 = (Controller_Gui1) fxLoader
                .getController();
        Scene scene = new Scene(anchorPane);
        //System.out.println(scene);
        controller_Gui1.setScene(scene);
        return controller_Gui1;
    }
}

Controller class

@FXML
Button B1 = new Button();
@FXML
public void handleButton1() {
    B1.setDisable(true);
}

Application class

public class MainApp_Gui1 extends Application {
    Controller_Gui1 cGui;

    @Override
    public void start(Stage primaryStage) throws Exception {
        initScene(primaryStage);
        primaryStage.show();
        System.out.println("asdasd");
        SceneSetting sceneSetting = new SceneSetting();
        //handleEvent();
        System.out.println("after");
        sceneSetting.setSceneAfter();
        System.out.println("after2");

    }

    // creating scene
    private void initScene(Stage primaryStage) throws IOException {
        primaryStage.setScene(getScene(primaryStage));

    }

    public Scene getScene(Stage primaryStage) {
        Controller_Gui1 cGui;
        cGui = FactoryClass.createGUI();
        return cGui.getScene();
    }

    public void ExcessFromOutside() {
        Platform.runLater(new Runnable() {
            public void run() {
               System.out.println(Platform.isFxApplicationThread());
               cGui.handleButton1();
            }
        });

    }

    public static void main(String[] args) {
        launch(args);
    }
}

I want to call ExcessFromOutside() method from another thread.

I got a null pointer exception while trying to update the GUI Here's my application class

public class MainAppGui1 extends Application {
Controller_Gui1 controller_Gui1;
@Override
public void start(Stage primaryStage) throws Exception {
    initScene(primaryStage);
    primaryStage.show();

}
// creating scene
public void initScene(Stage primaryStage) throws IOException {
    FXMLLoader fxLoader = new FXMLLoader();
    fxLoader.setLocation(MainApp_Gui1.class.getResource("/com/Gui_1.fxml"));
    AnchorPane anchorPane=new AnchorPane();
    anchorPane = (AnchorPane) fxLoader.load();
    Controller_Gui1 controller_Gui1 = (Controller_Gui1) fxLoader.getController();
    Scene scene = new Scene(anchorPane);
    primaryStage.setScene(scene);
}
@FXML
public  void ExcessFromOutside()
{
    Platform.runLater(new Runnable() {      
        @Override 
        public void run() {

            System.out.println("called atleast");
            controller_Gui1.handleButton1();

        }
    });
}
public static void main(String[] args) {
    launch(args);
}


}

and this is the class from where i tried to update the GUI

public class Hudai {
public static void main(String args[]) throws InterruptedException
{
    new Thread()
    {
        public void run()
        {
            MainAppGui1.main(null);
        }
    }.start();
    Thread.sleep(5000);
    MainAppGui1 m = new MainAppGui1();
    m.ExcessFromOutside();      
}

}

回答1:


To disable your button in a different thread you can use Task's updateValue.

Task<Boolean> task = new Task<Boolean>() {
    @Override
    public Boolean call() {
         ... // The task that this thread needs to do
         updateValue(true);
         ...
         return null;
    }
};
button.disableProperty().bind(task.valueProperty());

If you want to use a new thread to call a method, which alters the scene graph, the best chance you have is to use Platform.runLater() in it.

//code inside Thread
...
// code to run on the JavaFX Application thread
Platform.runLater(new Runnable() {
    @Override 
    public void run() {
         handleButton1();
    }
});
...



回答2:


You should get a NullPointerException when you run this program.

The problem is, the member of MainApp_Gui1

Controller_Gui1 cGui;

never gets a value.

Remove line "Controller_Gui1 cGui;" from this code:

public Scene getScene(Stage primaryStage) {
    // Hudai hudai = new Hudai(primaryStage);
    // return hudai.getScene();
    Controller_Gui1 cGui;
    cGui = FactoryClass.createGUI();
    return cGui.getScene();

}


来源:https://stackoverflow.com/questions/29252167/update-javafx-scene-graph-from-a-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!