Javafx - 使用Scene绑定后台任务

时间:2014-04-21 11:35:50

标签: javafx

我的应用程序有两个屏幕。

屏幕-1: 它有两个按钮和一个标签

1)下载:     如果我们点击这个,那么我们将开始下载过程,但我们仍然在screen1中,并允许您访问“导航”控件。

2)导航:如果我们点击这个,那么我们将重定向到屏幕-2。

屏幕-2:

1)返回:如果我们点击这个,那么我们将返回Screen-1。

在下载过程中,我也希望允许用户访问其他控件。如果我们开始下载过程并导航到其他屏幕并重定向到下载屏幕,那么我们将显示当前的下载进度,而不是将其打开为新鲜。为此,我实施了如下。我创建了一个用于实现此下载过程的类,但我无法从该类更新屏幕的UI。请帮帮我。

Screen-1

public class MainsceneController实现Initializable {

@FXML
Button Download, Navigate;
@FXML
Label percentage;
@FXML
HBox progTag;
SyncService service = new SyncService(MainsceneController.this);

/**
 * Initializes the controller class.
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
}

@FXML
void DownlaodManager() {
    service.downloadProjectFiles();
}

@FXML
void Naviagtion() {
    URL location = SecondSceneController.class.getResource("SecondScene.fxml");
    ViewManager.getInstance().setView(location);
}

}

Screen-2:

public class SecondSceneController实现Initializable {

/**
 * Initializes the controller class.
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}

@FXML
void goBack() {
    URL location = MainsceneController.class.getResource("mainscene.fxml");
    ViewManager.getInstance().setView(location);
}

}

Background downloading task

公共类SyncService {

long currentDownload, totalFileSize;
MainsceneController controller;
DownloadingFilesTask downloadingFilesTask;

public SyncService(MainsceneController controller) {
    this.controller = controller;
    downloadingFilesTask = new DownloadingFilesTask();
}
public void downloadProjectFiles() throws IOException {
    DownloadingFilesTask downloadingFilesTask = new DownloadingFilesTask();

    downloadingFilesTask.progressProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> ov, Number oldProgress, Number newProgress) {
            System.out.println("Progress changed");
            controller.percentage.setText("Progress changed:" + currentDownload);
        }
    });

    downloadingFilesTask.stateProperty().addListener(new ChangeListener<Worker.State>() {
        @Override
        public void changed(ObservableValue<? extends Worker.State> source, Worker.State oldState, Worker.State newState) {
            if (newState.equals(Worker.State.SUCCEEDED)) {
                System.err.println("Completed downloading files");
                controller.percentage.setText("Progress changed:" + currentDownload);
            }
        }
    });

    //progress listeners.
    ProgressBar bar = new ProgressBar();
    bar.progressProperty().bind(downloadingFilesTask.progressProperty());
    bar.visibleProperty().bind(downloadingFilesTask.runningProperty());
    controller.progTag.getChildren().clear();
    controller.progTag.getChildren().add(bar);

    new Thread(downloadingFilesTask).start();
}

class DownloadingFilesTask extends Task<Void> {

    @Override
    protected Void call() throws Exception {

        try {
            String fullUrl = "http://s3-us-west-2.amazonaws.com/absprod/media/25/manuals/53454a73d9eda$$53454a73d9f571397049971.mp4";
            String destLocation = "C:\\Users\\naresh.repalle\\Desktop\\ABS Test\\53454a73d9eda$$53454a73d9f571397049971.mp4";
            File destFile = new File(destLocation);

            URL downloadingUrl = new URL(fullUrl);
            RandomAccessFile file = null;
            InputStream stream = null;
            int downloaded = 0;
            int size = -1;


            try {
                // Open connection to URL.
                HttpURLConnection connection = (HttpURLConnection) downloadingUrl.openConnection();

                // Specify what portion of file to download.
                connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
                connection.setConnectTimeout(10 * 1000);
                connection.setReadTimeout(10 * 1000);
                // Connect to server.
                connection.connect();


                // Make sure response code is in the 200 range.
                if (connection.getResponseCode() / 100 != 2) {
                    System.err.println("Wrong response code while downloading file." + connection.getResponseCode());
                }

                // Check for valid content length.
                int contentLength = connection.getContentLength();
                if (contentLength < 1) {
                    System.err.println("Wrong file size while downloading file." + contentLength);
                }

                /*
                 * Set the size for this download if it hasn't been already set.
                 */
                if (size == -1) {
                    size = contentLength;
                }

                totalFileSize = size;

                // Open file and seek to the end of it.
                file = new RandomAccessFile(destFile, "rw");
                file.seek(downloaded);

                stream = connection.getInputStream();
                int MAX_BUFFER_SIZE = 1024;

                while (true) {
                    /*
                     * Size buffer according to how much of the file is left to download.
                     */
                    byte buffer[];
                    if (size - downloaded > MAX_BUFFER_SIZE) {
                        buffer = new byte[MAX_BUFFER_SIZE];
                    } else {
                        buffer = new byte[size - downloaded];
                    }

                    // Read from server into buffer.
                    int read = stream.read(buffer);

                    if (read == -1) {
                        System.out.println("read: " + read);
                        break;
                    }


                    // Write buffer to file.
                    file.write(buffer, 0, read);
                    downloaded += read;
                    currentDownload = downloaded;
                    stateChanged();

                }
            } catch (Exception e) {
                System.err.println("Exception in Downloading file: " + e.toString());
            } finally {
                /*
                 * Change status to complete if this point was reached because downloading
                 * has finished.
                 */
                // Close file.
                if (file != null) {
                    try {
                        file.close();
                    } catch (Exception e) {
                    }
                }

                // Close connection to server.
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (Exception e) {
                        System.err.println("exception in downloading: " + e.toString());
                    }
                }
            }
        } catch (Exception ex) {
            System.err.println("Unable to download file: " + ex);
        }
        return null;
    }

    private void stateChanged() {
        updateProgress(currentDownload, totalFileSize);
    }
}

}

1 个答案:

答案 0 :(得分:0)

您的SyncService无需重新加载FXML;它只需要与现有的控制器进行通信。一个简单的方法是只传递一个对SyncService的构造函数的引用:

public class SyncService {
    MainSceneController controller ;
    public SyncService(MainSceneController controller) {
        this.controller = controller ;
    }

    // ...
    public void downloadProjectFiles() throws IOException {
        DownloadingFilesTask downloadingFilesTask = new DownloadingFilesTask();

//      Remove the following:

//      URL location = MainsceneController.class.getResource("mainscene.fxml");

//      FXMLLoader fxmlLoader = new FXMLLoader();
//      fxmlLoader.setLocation(location);
//      fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());

//      final AnchorPane root = (AnchorPane) fxmlLoader.load(location.openStream());

      //get the controller
//      final MainsceneController controller = (MainsceneController) fxmlLoader.getController();

//       Then code as before
//       ...
    }
}

我想我实际上会采用不同的方式:我不喜欢SyncService和MainSceneController之间的强耦合。我将初始化MainSceneController中的进度条,将进度公开为SyncService中的属性并在控制器中绑定它。但是你应该能够使用更简单的方法来实现它。