0

I am having one code that send command to server.

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);
    }
}

and

public static boolean sendCommandToServer(Command command) {
    try {
        outStream.writeObject(command);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

And I am receiving result like below.

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();
            }
        }
    }
}

Now I want to wait for command to be successfully executed on server till the result of it is received by client. I want to show some Progress indicator type of UI ....how to do that? Thanks!

WeSt
  • 2,628
  • 5
  • 22
  • 37
Harsh Patel
  • 11
  • 1
  • 4

2 Answers2

0
  1. Use a Task or a Service for your long running server calls.
  2. Use Task.updateProgress() to inform on the current progress / work done.
  3. Bind the progressProperty of your running Task to a ProgressBar or ProgressIndicator.
Community
  • 1
  • 1
eckig
  • 10,964
  • 4
  • 38
  • 52
0

You specified the tags java and javafx. Here is my solution for javafx. It is a simple dialog that can be updated from 'outside' via binding.

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) {
    }
}

Example for usage (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);
    }
}

It looks like this:
progress

chris
  • 1,685
  • 3
  • 18
  • 28
  • Doesn't this update the progress bar from the background thread, instead of from the FX Application Thread? – James_D Jan 08 '15 at 14:24
  • I think the 'command' to update the progress is given in the new Thread started directly after creating the new WorkingDialog. This is needed to keep the ui alive. That shouldn't be a problem - why are you asking? – chris Jan 08 '15 at 14:33
  • If the ui (including the progress bar) is updated from outside of the FX Application Thread, it violates the threading rules of JavaFX, and the behavior is not deterministic. – James_D Jan 08 '15 at 15:39
  • I see... This could cause trouble for example with `tableview.getColumns().add(...)`. If I do such stuff i get a `java.lang.IllegalStateException: Not on FX application thread...` Is this solved by using `Platform.runLater(...)`? I mean it works but _should_ i do it? – chris Jan 08 '15 at 16:00
  • You should update the progress property of the progress bar on the FX Application Thread by using `Platform.runLater(...)` somewhere. Since you made everything else in your `WorkingDialog` class thread safe, it would make sense to make updating its `progress` property thread-safe too, though that is tricky. Why not use @eckig's suggested approach though? This handles all the thread safety for you, and more (e.g. it throttles too many calls to `updateProgress` so the FX Application Thread doesn't get flooded, which your code doesn't do). – James_D Jan 08 '15 at 16:04
  • The whole story (my class WorkingDialog is just a few days old): I have a application with some long running actions. So i wanted 1. some kind of notification so that the user knows that somethings going on (possibly with a progressbar), 2. the ui shouldn't freeze, 3. the user shouldn't be able to use buttons, menus or whatever until the actions are done. I tried several stuff with the Task class but that all seems to me too complex. So i want to create a 'all purpose class for long running actions'. Maybe we should discuss this in a new question. What do you think? – chris Jan 08 '15 at 16:29