【问题标题】:java.lang.IllegalStateException: Not on FX application thread Calling Functionjava.lang.IllegalStateException:不在 FX 应用程序线程调用函数上
【发布时间】:2016-02-13 16:43:51
【问题描述】:

发生了一些奇怪的事情。直到 10 分钟前,我对这段代码没有任何问题。但现在我从外部线程更新 JUST 我的 VBOX 时遇到问题。

这是我的三门课:

控制器类:

public class Controller implements Initializable{
@FXML
private VBox slaveVbox;

private ButtonBar newNode = new ButtonBar();
private Circle c= new Circle();
private Button b= new Button();
private Label lname = new Label();
private Label lIMEI = new Label();
private Label lroot = new Label();

@Override
public void initialize(URL location, ResourceBundle resources) {
}

public void create(String imei, String permission,boolean isOnline) throws IOException{
    if(!alreadyExist(imei)){
    newNode = new ButtonBar();
    b = setButtonSpec(imei + "btnHavefun");
    c = setCircleSpec(imei + "statuOnline", isOnline);
    lname= setLNameSpec(imei + "name");
    lIMEI = setLIMEISpec(imei + "Imei");
    lroot = setLrootSpec(imei + "root", permission);
    newNode.getButtons().addAll(lname,lIMEI,lroot,b,c);
    slaveVbox.getChildren().addAll(newNode);
   }
  }
}

主类:

public class MainApp extends Application {
 FXMLLoader loader2;
 private Stage primaryStage;
 private BorderPane rootLayout;

@Override
public void start(Stage primaryStage) throws IOException {
    this.primaryStage = primaryStage;
    this.primaryStage.setTitle("Thypheon Application");
    initRootLayout();
    Controller controller2 = initDesign();
    Connection con = new Connection(controller2);
    Thread t = new Thread(con);
    t.start();

    primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
           @Override
           public void handle(WindowEvent e) {
              Platform.exit();
              System.exit(0);
           }
        });
}

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

public void initRootLayout(){
    try {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("RootLayout.fxml"));
        rootLayout = (BorderPane) loader.load();
        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public Controller initDesign(){
    try {
        FXMLLoader loader2= new FXMLLoader(getClass().getResource("Design.fxml"));
        AnchorPane anchor  = (AnchorPane) loader2.load();
        rootLayout.setCenter(anchor);
        Controller controller = loader2.getController();
        return controller;

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }

}


public Stage getPrimaryStage(){
    return primaryStage;
}

 }

连接线程:

public class Connection implements Runnable {
 String result;
 Controller controller;

   public Connection(Controller controller) {
       this.controller = controller;
   }

@Override
public void run() {
        try {
            controller.create("jhgjhgjh", "dssf", true);
    } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 }

调试应用程序一切正常,直到我到达slaveVbox.getChildren().addAll(newNode); 出现异常.. 在尝试解决这个问题后,我发现如果我创建一个 ButtonBar 并将它从 Main(在 start() 内部)插入到 slaveVbox 中,它工作正常。所以我已经绑定在我的 start() 中添加 controller2.create("FIRST", "FIRST", true);函数如下:

@Override
public void start(Stage primaryStage) throws IOException {
    this.primaryStage = primaryStage;
    this.primaryStage.setTitle("Thypheon Application");
    initRootLayout();
    Controller controller2 = initDesign();
    controller2.create("FIRST", "FIRST", true);
    Connection con = new Connection(controller2);
    Thread t = new Thread(con);
    t.start();

    primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
           @Override
           public void handle(WindowEvent e) {
              Platform.exit();
              System.exit(0);
           }
        });
}

但显然我的应用程序显示了两个 ButtonBars...一个在 start() 函数中创建,一个在 Connection Thread 中创建。我怎样才能避免这种情况?为什么我不能直接从我的 Connecton 线程直接在我的 VBox 中添加项目??

【问题讨论】:

    标签: multithreading exception javafx controller


    【解决方案1】:

    您不能从 FX 应用程序线程以外的线程更新 UI。例如,请参阅Application documentation 中的“线程”部分。

    完全不清楚您为什么在这里使用后台线程:您正在调用的方法中似乎没有任何长时间运行的代码。一般来说,如果您有长时间运行的代码要调用,您可以在后台线程中调用它,然后通过将 UI 更新包装在 Platform.runLater(...) 中来更新 UI。

    public class Connection implements Runnable {
      String result;
      Controller controller;
    
       public Connection(Controller controller) {
           this.controller = controller;
       }
    
       @Override
       public void run() {
            try {
                // execute long-running code here...
    
                // perform any updates to the UI on the FX Application Thread:
                Platform.runLater(() -> {
                    // code that updates UI
                });
    
                // more long-running code can go here...
    
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
       }
    }
    

    【讨论】:

    • 理论上我简化了我的代码..但是我有一个从套接字读取数据的while循环..我会尝试你的建议..我很快就会到
    猜你喜欢
    • 2015-06-09
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多