Java 主应用程序线程在到达方法末尾之前不更新GUI

Java 主应用程序线程在到达方法末尾之前不更新GUI,java,javafx,Java,Javafx,我在应用程序中有一个连接按钮,在堆栈窗格上有两个窗格。第一个窗格是聊天窗格,第二个窗格是在其背景上设置了.gif的加载程序 我想做的是,单击“连接”后,我想显示加载程序(在其背景上移动gif),然后等待delegate.connectToServer(..)方法结束,然后关闭加载程序窗格并切换回聊天窗格 在当前代码中,javaFX应用程序线程似乎没有可视化对GUI所做的更改,直到它到达connectClicked()方法的末尾,这意味着加载程序窗格没有被显示 我尝试将setConnectionS

我在应用程序中有一个连接按钮,在堆栈窗格上有两个窗格。第一个窗格是聊天窗格,第二个窗格是在其背景上设置了.gif的加载程序

我想做的是,单击“连接”后,我想显示加载程序(在其背景上移动gif),然后等待delegate.connectToServer(..)方法结束,然后关闭加载程序窗格并切换回聊天窗格

在当前代码中,javaFX应用程序线程似乎没有可视化对GUI所做的更改,直到它到达connectClicked()方法的末尾,这意味着加载程序窗格没有被显示

我尝试将setConnectionStatus方法的内容作为一个线程中的任务运行,但在执行此操作时,我收到了标签对象的setText方法导致的
noton fx应用程序线程
异常,但是加载程序gif显示得很好

我还尝试过像这样使用暂停转换:

@FXML
public void connectClicked() {
    setConnectionStatus(CONNECTING);
    PauseTransition pause = new PauseTransition(Duration.seconds(0.1));

    pause.setOnFinished(event -> {
        try {
            delegate.connectToServer(connectionConfig.getServerAddress().getIp(),
                        connectionConfig.getServerAddress().getPort(),
                        connectionConfig.getTimeout());
            setConnectionStatus(CONNECTED);
            } catch (ConnectionException e) {
                setConnectionStatus(DISCONNECTED);
                //todo reconnect dialog
            } catch (FatalException e) {
                handleFatalError("Connection error", e.getMessage());
            }
        });
        pause.play();
    }
这导致加载程序窗格显示移动0.1秒,之后动画停止(加载程序窗格保持可见,仅gif停止)

我还尝试用
Platform.runLater()
Thread
包装try-catch块,但没有效果

我不能使用
Platform.runLater
显示加载程序,因为我希望立即执行gui更改,而不是“将来某个时候”

以下是完整的代码:

@FXML public VBox loader;
@FXML public SplitPane chatPane;
@FXML public MenuItem connectMenuItem;
@FXML public MenuItem disconnectMenuItem;
@FXML public Label connectionStatus;

@FXML
public void connectClicked() {
       setConnectionStatus(CONNECTING);
        try {
            delegate.connectToServer(connectionConfig.getServerAddress().getIp(),
                    connectionConfig.getServerAddress().getPort(),
                    connectionConfig.getTimeout());
            setConnectionStatus(CONNECTED);

        } catch (ConnectionException e) {
            setConnectionStatus(DISCONNECTED);
            //todo reconnect dialog
        } catch (FatalException e) {
            handleFatalError("Connection error", e.getMessage());
        }
    }

     private void setConnectionStatus(ConnectionStatus status) {
        switch (status) {
            case CONNECTED:
                setStatusLabel("Connected", GREEN);
                setConnectionMenu(false, true);
                showChatPane();
                break;
            case DISCONNECTED:
                setStatusLabel("Not Connected", RED);
                setConnectionMenu(true, false);
                showChatPane();
                break;
            case CONNECTING:
                setStatusLabel("Connecting...", BLUE);
                setConnectionMenu(false, false);
                showLoader();
                break;
            case DISCONNECTING:
                setStatusLabel("Disconnecting...", BLUE);
                setConnectionMenu(false, false);
                showLoader();
                break;
        }
    }

    private void setStatusLabel(String text, Color color) {
        connectionStatus.setText(text);
        connectionStatus.setTextFill(color);
    }

    private void setConnectionMenu(boolean isConnectEnabled, boolean isDisconnectEnabled) {
        connectMenuItem.setDisable(!isConnectEnabled);
        disconnectMenuItem.setDisable(!isDisconnectEnabled);
    }

    private void showLoader() {
        chatPane.setVisible(false);
        loader.setVisible(true);
    }

    private void showChatPane() {
        chatPane.setVisible(true);
        loader.setVisible(false);
    }

看起来用一个线程包装try-catch块起作用了,但之前它没有起作用,因为我使用的是thread.run()而不是thread.start()


此外,我还必须在线程体中添加Platform.runLater
setConnectionStatus
方法。

将您的逻辑放在与UI线程不同的线程中。使用线程包装try-catch块没有任何效果,加载程序窗格仍然没有显示“JavaFX后台任务”的Google,我相信您会找到大量资源。非UI逻辑(如建立连接,需要很长时间)必须在UI线程之外执行。UI逻辑(如更新标签)必须在UI线程上完成。将逻辑放在线程中有效,这只是我的愚蠢,因为我使用的是thread.run()而不是thread.start()