JavaFX FXML communication between Application and Controller classes

后端 未结 1 804
栀梦
栀梦 2021-01-03 17:34

I am trying to get and destroy an external process I\'ve created via ProcessBuilder in my FXML application close, but it\'s not working. This is based on the helpful advice

相关标签:
1条回答
  • 2021-01-03 18:21

    The approach is right, but there are few problems.

    You've created the FXMLLoader named fxmlLoader but then you call FXMLLoader.load() which is static method and is not connected with instance you've created before.

    Also using static method to intercommunication is not very good (imagine you'll want to have several processes). Better store myController to a field and call it in the stop() method.

    Even better would be to add corresponding utility method to Controller and call it from main app, because main app doesn't seem to use Process itself.


    Here goes short app to demonstrate all described:

    public class DoTextAreaLog extends Application {
    
        private LoggController controller;
    
        @Override
        public void start(Stage stage) throws IOException{
                FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("logg.fxml"));
                VBox root = (VBox)fxmlLoader.load();
                controller = (LoggController) fxmlLoader.getController();
    
                stage.setScene(new Scene(root, 400, 300));
                stage.show();
        }
    
        @Override
        public void stop() throws Exception {
            super.stop();
            controller.destroy();
        }
    
        public static void main(String[] args) { launch(); }
    }
    

    Controller:

    public class LoggController implements Initializable {
    
        @FXML private TextArea textarea;
    
        @FXML private void onAction(ActionEvent event) {
            destroy();
        }
    
        private Process p;
    
        public void destroy() {
            if (p != null) {
                p.destroy();
            }
        }
    
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            try {
                p = new ProcessBuilder("ping", "stackoverflow.com", "-n", "100").start();
    
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            try (BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
                                String line;
    
                                while ((line = bri.readLine()) != null) {
                                    log(line);
                                }
                            }
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                }).start();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    
        private void log(final String st) {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    textarea.setText(st + "\n" + textarea.getText());
                }
            });
        }
    }
    

    logg.fxml:

    <VBox id="root" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml"  fx:controller="fxml.LoggController">
        <TextArea fx:id="textarea"/>
        <Button text="Stop The Madness!" onAction="#onAction"/>
    </VBox>
    
    0 讨论(0)
提交回复
热议问题