首页 > 解决方案 > 当我调用新方法时,JavaFX FadeTransition 结束其他 SetVisbilities 停止工作

问题描述

我想在我的应用程序的窗格中创建一个 FadeTransition。此外,通过这个 FadeTransition,我将窗格内一些 JavaFX 的可见性设置为 false,以使它们消失。它工作正常,但是,当我在 FadeTransition 之后调用另一个名为 waitForResponse(event) 的方法时,它就会停止工作。我不知道为什么。如果我评论 waitForResponse(event) FadeTransitions 再次开始工作。我认为可能是waitForResponse(event)中的Socket和InputStreamReader有问题,但是我测试了将其取出并在此方法中制作另一个基本的东西仍然不起作用。我进行了其他测试,发现如果我在其后放置任何 bufferedReader、其他循环或决策结构,FadeTransition 和其他可见性更改将不起作用。

这是代码:

public class LoadingScreenController implements Initializable {

    // Socket que vai ser utilizado nos vários métodos para conversar com o servidor
    private Socket cliente;

    // PrintWriter que vai ser utilizado pelos vários métodos e vai passar o
    // argumento para o switch case
    private PrintWriter pr;
    
    private InputStreamReader in;
    
    private BufferedReader bf;
    
    private String option;
    
    private String response;

    @FXML
    private Button refreshButton;

    @FXML
    private ImageView loadingGif;

    @FXML
    private Label txtLabel;
    
    @FXML
    private AnchorPane rootPane;

    public String getOption() {
        return option;
    }

    public void setOption(String option) {
        this.option = option;
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }
    
    @FXML
    private void makeFadeInTransition() {
        FadeTransition fadeTransition = new FadeTransition(Duration.seconds(1), loadingGif);
        fadeTransition.setFromValue(0.0);
        fadeTransition.setToValue(1.0);
        fadeTransition.play();
    }

    @FXML
    private void onRefreshButtonAction(ActionEvent event) {
        if (option == null) {
            throw new IllegalStateException("Entity was null");
        }
        refreshButton.setVisible(false);
        refreshButton.setDisable(true);
        txtLabel.setVisible(false);
        makeFadeInTransition();
        sendOptionToServer(event);
    }
    
    @FXML
    private void sendOptionToServer(ActionEvent event) {
        
            try {
                cliente = new Socket("localhost", 3322);
                pr = new PrintWriter(cliente.getOutputStream());
                in = new InputStreamReader(cliente.getInputStream());
                bf = new BufferedReader(in);
                pr.println(option);
                pr.flush();
                waitForReponse(event, bf);
            } catch (IOException e) {
                e.printStackTrace();
            }
            
    }
    
    private void waitForReponse(ActionEvent event, BufferedReader bf) throws IOException {
        response = bf.readLine();
        switch (response) {
        case "a":
            Utils.currentStage(event).close();
            break;
        }
    }
}

标签: socketsjavafx

解决方案


您的sendOptionToServer(...)方法,特别是您的waitForResponse(...)方法,包含阻塞调用,这些调用会阻塞执行,直到它们完成(即,直到您收到来自服务器的响应)。由于您在 FX 应用程序线程上运行这些,因此您会阻止该线程执行其正常工作,直到这些调用完成。这意味着在您收到并处理来自服务器的响应之前,它不会更新 UI 或处理任何用户事件。

您应该将阻塞方法的调用放在后台线程中,以允许 FX 应用程序线程同时进行。javafx.concurrentAPI使这相当容易做到;这里一个Task应该足够了。

这是一个使用Task. 我还使用了“尝试资源”来确保正确关闭需要关闭的所有内容。

@FXML
private void sendOptionToServer(ActionEvent event) {
    
    Task<String> serverCommunicationTask = new Task<>() {
        @Override
        protected String call() throws Exception {
            try (
                Socket cliente = new Socket("localhost", 3322);
                PrintWriter pr = new PrintWriter(cliente.getOutputStream());
                BufferedReader bf = new BufferedReader(new InputStreamReader(cliente.getInputStream()));
            ) {
                pr.println(option);
                pr.flush();
                return bf.readLine();
            }
        }
    };

    serverCommunicationTask.setOnSucceeded(event -> {
        if ("a".equals(serverCommunicationTask.getValue())) {
            rootPane.getScene().getWindow().hide();
        }
    });

    serverCommunicationTask.setOnFailed(event -> {
        event.getException().printStackTrace();
        // handle exception...
    });

    Thread thread = new Thread(serverCommunicationTask);
    thread.setDaemon(true);
    thread.start();
        
}

推荐阅读