Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用javafx中的进度指示器等待某些操作完成?_Java_Sockets_Javafx - Fatal编程技术网

如何使用javafx中的进度指示器等待某些操作完成?

如何使用javafx中的进度指示器等待某些操作完成?,java,sockets,javafx,Java,Sockets,Javafx,我有一个向服务器发送命令的代码 public static void createAndSendCommand(String action, byte[] data) { if (action.equals(OE_Constants.ACTION_UPDATE)) { File file = new File(OE_Constants.FILE_BACKUP_TOPOLOGY); Command command = ConnectionManager.po

我有一个向服务器发送命令的代码

public static void createAndSendCommand(String action, byte[] data) {
    if (action.equals(OE_Constants.ACTION_UPDATE)) {
        File file = new File(OE_Constants.FILE_BACKUP_TOPOLOGY);
        Command command = ConnectionManager.populateData(file);
        FrontEndClient.sendCommandToServer(command);
    }
}

我收到的结果如下

public void receiveResultFromServer() {
    try {
        while(!clientSocket.isClosed()) {
            CommandExecResult result;
            try {
                result = (CommandExecResult) inStream.readObject();
                ConnectionManager.parseCommandExecutionResult(result);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
现在,我想等待命令在服务器上成功执行,直到客户端收到命令的结果。我想展示一些进度指示器类型的UI…如何做到这一点? 谢谢

对于长时间运行的服务器调用,请使用。 用于通知当前进度/完成的工作。 将正在运行的任务的绑定到或。
您指定了标记java和javafx。这是我的javafx解决方案。这是一个简单的对话框,可以通过绑定从“外部”进行更新

WorkingDialog.java:

package stackoverflow.progress;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;

public final class WorkingDialog extends Stage implements Initializable {

    private static final Logger LOG = Logger.getLogger(WorkingDialog.class.getName());
    public SimpleDoubleProperty progress = new SimpleDoubleProperty(0);

    public WorkingDialog(String title, Stage owner) {
        super();

        setTitle(title);
        initStyle(StageStyle.UTILITY);
        initModality(Modality.APPLICATION_MODAL);
        initOwner(owner);

        double w = 300;
        double h = 200;

        setWidth(w);
        setHeight(h);

        double dx = (owner.getWidth() - w) / 2;
        double dy = (owner.getHeight() - h) / 2;

        setX(owner.xProperty().get() + dx);
        setY(owner.yProperty().get() + dy);

        setResizable(false);
        showDialog(progress);
    }

    public void hideDialog() {
        Platform.runLater(() -> {
            hide();
        });
    }

    public void setTitleText(String title) {
        Platform.runLater(() -> {
            setTitle(title);
        });
    }

    private void showDialog(SimpleDoubleProperty progress) {
        //scene : gridPane : 0,0->progressbar,0,1->borderpane : center->button
        GridPane gridPane = new GridPane();

        gridPane.setGridLinesVisible(false);
        gridPane.setPadding(new Insets(10));
        gridPane.setHgap(5);
        gridPane.setVgap(5);

        setOnCloseRequest((WindowEvent e) -> {
            e.consume();
        });

        ProgressBar pb = new ProgressBar(-1);
        pb.setPrefWidth(300);
        pb.progressProperty().bind(progress);
        BorderPane borderPane = new BorderPane(pb);
        gridPane.add(borderPane, 0, 0);

        Scene scene = new Scene(gridPane);
        setScene(scene);
        sizeToScene();
        show();
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
    }
}
WorkingDialogTest.java的用法示例:

package stackoverflow.progress;

import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class WorkingDialogTest extends Application {

    private static final Logger LOG = Logger.getLogger(WorkingDialogTest.class.getName());

    @Override
    public void start(Stage primaryStage) {
        Group group = new Group();
        Scene scene = new Scene(group);

        primaryStage.setTitle("Dialogs");
        primaryStage.setWidth(600);
        primaryStage.setHeight(400);

        Button button = new Button("function");
        button.setOnAction((ActionEvent e) -> {

            WorkingDialog wd = new WorkingDialog("title", primaryStage);
            new Thread(() -> {
                int counter = 10;
                for (int i = 0; i < counter; i++) {
                    try {
                        wd.progress.set(1.0 * i / (counter - 1)); 
                        Thread.sleep(1000); //<-------- do more useful stuff here
                    } catch (InterruptedException ex) {
                    }
                }
                wd.hideDialog();
            }).start();

        });

        HBox hbox = new HBox(button);
        group.getChildren().addAll(hbox);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
看起来是这样的:

这不是从后台线程而不是从FX应用程序线程更新进度条吗?我认为更新进度的“命令”是在创建新工作对话框后直接启动的新线程中给出的。这是保持ui活动所必需的。这应该不是问题-你为什么要问?如果包含进度条的ui是从FX应用程序线程外部更新的,它违反了JavaFX的线程规则,并且行为是不确定的。我明白了。。。这可能会导致问题,例如tableview.getColumns.add。。。。如果我做了这些事情,我会得到一个java.lang.IllegalStateException:不在FX应用程序线程上。。。这是通过使用Platform.runLater解决的吗。。。?我的意思是它可以工作,但我应该这样做吗?你应该使用Platform.runLater更新FX应用程序线程上进度条的进度属性。。。在某处由于您使WorkingDialog类中的所有其他内容都是线程安全的,所以更新其progress属性也应该是线程安全的,尽管这很棘手。为什么不使用@eckig建议的方法呢?这将为您处理所有线程安全问题,以及更多问题,例如,它限制了对updateProgress的太多调用,因此FX应用程序线程不会被淹没,而您的代码不会这样做。
package stackoverflow.progress;

import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class WorkingDialogTest extends Application {

    private static final Logger LOG = Logger.getLogger(WorkingDialogTest.class.getName());

    @Override
    public void start(Stage primaryStage) {
        Group group = new Group();
        Scene scene = new Scene(group);

        primaryStage.setTitle("Dialogs");
        primaryStage.setWidth(600);
        primaryStage.setHeight(400);

        Button button = new Button("function");
        button.setOnAction((ActionEvent e) -> {

            WorkingDialog wd = new WorkingDialog("title", primaryStage);
            new Thread(() -> {
                int counter = 10;
                for (int i = 0; i < counter; i++) {
                    try {
                        wd.progress.set(1.0 * i / (counter - 1)); 
                        Thread.sleep(1000); //<-------- do more useful stuff here
                    } catch (InterruptedException ex) {
                    }
                }
                wd.hideDialog();
            }).start();

        });

        HBox hbox = new HBox(button);
        group.getChildren().addAll(hbox);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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