所以,我有一个非常非常简单的应用程序,应该处理下载某些文件并将它们更新到某个目录中。该应用程序有一个带有状态栏的简单界面,可以告诉用户下载过程的进展情况。到目前为止,一切顺利。
我有一些扩展javafx.concurrent.Task类的类的实现。这些类处理每个系统的文件下载和保存,并考虑每个系统的特殊性。下载过程本身(实际上来自远程数据库)对于每个人来说都是相同的,因此,它是在另一个名为 FileDownloader 的类中实现的,因为它自然应该是可重用的。
因此,我们有一个带有 call() 方法的 UpdateTask 类,该方法又调用 FileDownloader 类中的某些方法。
问题是:我需要将一个 progressProperty 绑定(bind)到该栏,但只有 UpdateTask 有此属性,而我想在栏中显示大部分工作是在FileDownloader内部完成的。我无法从下载方法中调用 updateProgress,因为它不在 Task 类中。我无法将任务传递到方法中并在那里调用更新方法。我无法在进度属性上创建监听器并监听下载器类内字段的更改。看来我无能为力,唯一真正的解决方案是计算 call() 方法内完成的工作。祸哉是我。
是否有解决方案,不需要我编写可重用性较低的代码?示例代码如下:
public class UpdateTask extends Task<Void> {
@Override
protected Void call() throws Exception {
//some other operations are performed before this part
FileDownloader downloader = new FileDownloader();
//The stuff I wanna count is in there :(
boolean isDownloaded = downloader.downloadSysVersion();
//some other stuff happens that depends on the completion of the download
}
无论谁向我展示如何从 downloadSysVersion 方法内部获取信息,都将获得免费的互联网 cookie。
最佳答案
在 FileDownloader
类中添加一个表示进度的属性。例如,如果您想公开下载的字节数,您可以这样做
public class FileDownloader {
private final ReadOnlyLongWrapper bytesDownloaded = new ReadOnlyLongWrapper();
public final long getBytesDownloaded() {
return bytesDownloaded.get();
}
public final ReadOnlyLongProperty bytesDownloadedProperty() {
return bytesDownloaded.getReadOnlyProperty();
}
private long totalBytes ;
public long getTotalBytes() {
return totalBytes ;
}
// other code as before...
public boolean downloadSysVersion() {
// code as before, but periodically call
bytesDownloaded.set(...);
// ...
}
}
现在你做到了
@Override
protected Void call() throws Exception {
FileDownloader downloader = new FileDownloader();
downloader.bytesDownloadedProperty().addListener((obs, oldValue, newValue) ->
updateProgress(newValue.longValue(), downloader.getTotalBytes()));
boolean isDownloaded = downloader.downloadSysVersion();
// ...
}
如果您想让 FileDownloader
类独立于整个 JavaFX API(包括属性类),您可以使用 LongConsumer
来代替:
public class FileDownloader {
private LongConsumer progressUpdate ;
public void setProgressUpdate(LongConsumer progressUpdate) {
this.progressUpdate = progressUpdate ;
}
private long totalBytes ;
public long getTotalBytes() {
return totalBytes ;
}
public boolean downloadSysVersion() {
// periodically do
if (progressUpdate != null) {
progressUpdate.accept(...); // pass in number of bytes downloaded
}
// ...
}
}
在本例中,您的任务如下所示
@Override
protected Void call() throws Exception {
FileDownloader downloader = new FileDownloader();
downloader.setProgressUpdate(bytesDownloaded ->
updateProgress(bytesDownloaded, downloader.getTotalBytes()));
boolean isDownloaded = downloader.downloadSysVersion();
// ...
}
使用这两种设置中的任何一种,您都可以照常将进度条的 progressProperty
绑定(bind)到任务的 progressProperty
。
关于JavaFX - 将另一个类的属性绑定(bind)到状态栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31734527/