我的应用程序有两个屏幕。
屏幕-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);
}
}
}
答案 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中的属性并在控制器中绑定它。但是你应该能够使用更简单的方法来实现它。