javamultithreadingjavafxfxmlwindow-management

javafx close window from other class


I'm connection to a server in a small javaFX window. The connection is made by a new thread. But I want the window to close when the connection is established. How do I make that happen?

here's what I've tried.

package se.skplay.scaenicos.subWindows.casparConnection;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import se.skplay.scaenicos.Connections;

public class CasparConnectonController implements Initializable {

    @FXML private TextField hostFiled = new TextField();
    @FXML private TextField portFiled = new TextField();
    @FXML private Button cancel;
    @FXML private Button connect;
    @FXML private Label connecting = new Label();

    private int port = 5250;
    private String host = "localhost";
    static private Stage stage;

    @FXML
    protected void connect() throws IOException {
            if (!hostFiled.getText().equals("")) {
                host = hostFiled.getText();
            }
            if (!portFiled.getText().equals("")) {
                port = Integer.parseInt(portFiled.getText());
            }
            connecting.setText("Connecting...");

            stage = (Stage) connect.getScene().getWindow();
            Connect conCasp = new Connect(host, port);
            conCasp.start();

        try {
            if (Connections.getCaspar().isConnected()) {
                closeWindow();
            }
        } catch (NullPointerException e) {

        }

    }

    private void closeWindow() {
        stage = (Stage) connect.getScene().getWindow();
        stage.close();
    }

    @FXML
    protected void cancel() {
        closeWindow();
    }

    public static Stage getStage() {
        return stage;
    }


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

    }

}

The class that connects to the server

package se.skplay.scaenicos.subWindows.casparConnection;

import java.io.IOException;

import se.skplay.scaenicos.Connections;

public class Connect extends Thread {

    private String host;
    private int port;

    public Connect(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void run() {
        try {
            connect();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void connect() throws IOException {
        Connections.setCaspar(host, port);
        CasparConnectonController.getStage().close();
    }

}

Solution

  • Make your Connect class a subclass of Task<Void> instead:

    package se.skplay.scaenicos.subWindows.casparConnection;
    
    import java.io.IOException;
    
    import javafx.concurrent.Task ;
    
    import se.skplay.scaenicos.Connections;
    
    public class Connect extends Task<Void> {
    
        private String host;
        private int port;
    
        public Connect(String host, int port) {
            this.host = host;
            this.port = port;
        }
    
        @Override
        public Void call() {
            try {
                connect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private void connect() throws IOException {
            Connections.setCaspar(host, port);
            // You can never close a stage from a background thread
            // CasparConnectonController.getStage().close();
        }
    
    }
    

    And then you can use the onSucceeded handler to close the stage:

    @FXML
    protected void connect() throws IOException {
            if (!hostFiled.getText().equals("")) {
                host = hostFiled.getText();
            }
            if (!portFiled.getText().equals("")) {
                port = Integer.parseInt(portFiled.getText());
            }
            connecting.setText("Connecting...");
    
            stage = (Stage) connect.getScene().getWindow();
            Connect conCasp = new Connect(host, port);
    
            conCasp.setOnSucceeded(event -> closeWindow());
    
            new Thread(conCasp).start();
    
    }