【问题标题】:Update JavaFX scene graph from a Thread从线程更新 JavaFX 场景图
【发布时间】:2015-05-28 22:01:00
【问题描述】:

我需要根据客户端输入更新我的 GUI。从后台任务调用我的控制器类方法有效。但它不能更新 GUI,因为它不是 JavaFX 应用程序线程..请帮助。

我尝试了许多相关的Q & A,但我仍然感到困惑。

我应该使用 Platform. runLater 还是 Task

这是我创建controller 类实例的类

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;
    }
}

控制器类

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

应用类

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

我想从另一个线程调用ExcessFromOutside() 方法。

尝试更新 GUI 时出现空指针异常 这是我的应用程序类

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


}

这是我尝试更新 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();      
}

}

【问题讨论】:

  • 您能否添加一些代码来向我们展示究竟是什么不适合您?
  • 我应该使用任务吗?这是我的第一篇文章……所以考虑一下……
  • 你为什么使用MainAppGui1.main(null);
  • 您可以直接从任何类启动 GUI。请转至Starting JavaFX from Main method of class which doesn't extend Application
  • 谢谢。但这不能解决我的问题。仍然得到空指针异常

标签: model-view-controller javafx javafx-8


【解决方案1】:

要在不同的线程中禁用您的button,您可以使用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());

如果你想使用一个新线程来调用一个改变场景图的方法,你最好的机会是在其中使用Platform.runLater()

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

【讨论】:

  • 如果你想打电话给updateValue(true),你需要一个Task&lt;Boolean&gt;
  • 哦,是的,正确。写 sn-p 时出现错字,谢谢指出:)
  • 非常感谢。Platform.runlater 更适合我的项目..但它仍然无法正常工作。我不知道为什么..我的 GUI 从鼠标点击改变..但我无法通过应用程序线程中使用 platform.runlater 的方法更新它。我的项目是一个两人游戏。我需要禁用一个按钮基于客户端消息的网格。所以我想从接收输入流的线程更改我的 GUI。谢谢
  • 如果您已经使用Application Thread,则不需要Platform.runLater。我真的不明白你的问题。您能否创建一个MCVE 并将其添加到您的问题中,以帮助我理解场景?
  • 你的实现没有任何意义。
【解决方案2】:

当你运行这个程序时你应该得到一个 NullPointerException。

问题是,MainApp_Gui1 的成员

Controller_Gui1 cGui;

永远不会得到值。

删除“Controller_Gui1 cGui;”行从此代码:

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

}

【讨论】:

  • 另外,如果你使用@FXML 来初始化一个Button,你就不必调用new。所以@FXML按钮B1; // 没有新按钮
  • 谢谢你,我刚开始使用 javafx ..这就是为什么......我只想用这个方法更新我的 gui
  • 问题是我的 ExcessFromOutside 方法在关闭窗口后被调用
  • 它正在工作,但我想用方法进行更改......但我不能
  • 哦,但是你为什么要在关闭窗口的情况下修改那个按钮,我不明白你想用你的应用程序实现什么。
猜你喜欢
  • 2020-09-30
  • 2018-07-30
  • 2019-01-26
  • 2015-05-30
  • 2016-07-28
  • 2015-05-16
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多