Issue
I'm creating a JavaFX application which would send multiple files over network, and I want to have a progress bar for the number of bytes sent. I already have the total size of the files which are about to be sent, however, I don't know how to increase the progress bar.
The problem is, I am sending the files concurrently, so I can't just set progress in my download class, as that would get overwritten by another threat.
This is what my download class look like:
iStream = socket.getInputStream();
bufferSize = socket.getReceiveBufferSize();
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) >= 0) {
bos.write(bytes, 0, count);
}
bos.close();
is.close();
And I'm executing the class the following way:
List<Callable<String>> downloadTasks = new ArrayList<>();
Callable<String> download = new Download(new File(path), portnumber);
downloadTasks.add(download);
es.invokeAll(downloadTasks);
I have the total number of bytes in variable long totalSize
in both classes.
Can you please help me on how I would achieve the bytes progress bar? Thanks
Solution
You can only update the progress bar from a single thread: the FX Application Thread. So the threading issue is moot; you can just increment a property representing the total number of bytes downloaded, and arrange to only update it from that thread.
So something like:
public class UploadProgressMonitor {
private final long totalBytes ;
private long downloadedBytes ;
private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper() ;
public UploadProgressMonitor(long totalBytes) {
this.totalBytes = totalBytes ;
}
private void doIncrement(long bytes) {
downloadedBytes += bytes ;
progress.set(1.0 * downloadedBytes / totalBytes);
}
public void increment(long bytes) {
if (Platform.isFxApplicationThread()) {
doIncrement(bytes);
} else {
Platform.runLater(() -> doIncrement(bytes));
}
}
public ReadOnlyDoubleProperty progressProperty() {
return progress.getReadOnlyProperty() ;
}
public final double getProgress() {
return progressProperty().get();
}
}
Now you can do things like:
long totalBytes = ... ;
UploadProgressMonitor monitor = new UploadProgressMonitor(totalBytes);
progressBar.progressProperty().bind(monitor.progressProperty());
and if you give each task a reference to the UploadProgressMonitor
it just needs to do:
int count;
while ((count = is.read(bytes)) >= 0) {
bos.write(bytes, 0, count);
monitor.increment(count);
}
Answered By - James_D