Javafx Task - 从方法更新进度
Javafx Task - update progress from a method
在 JavaFX 应用程序中,我希望根据我在另一个 class 中实现的一些工作逻辑来更新状态栏。
我不知道如何将我希望将工作逻辑传递给方法(而不是将其写在任务中)与了解工作进度百分比相结合。
这是带有任务的控制器示例:
public class FXMLDocumentController implements Initializable {
@FXML private Label label;
@FXML ProgressBar progressBar;
@FXML
private void handleButtonAction(ActionEvent event) {
Service<Void> myService = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
try {
DatabaseFunctionality.performWorkOnDb();
//updateProgress(1, 1);
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
progressBar.progressProperty().bind(myService.progressProperty());
myService.restart();
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
这是帮手class:
public class DatabaseFunctionality {
public static void performWorkOnDb () throws InterruptedException {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
//Update progress
}
}
}
谢谢
这里有几个选项。一种是按照 Uluk 的建议去做,并在你的 DatabaseFunctionality
class:
中公开一个可观察的 属性
public class DatabaseFunctionality {
private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper();
public double getProgress() {
return progressProperty().get();
}
public ReadOnlyDoubleProperty progressProperty() {
return progress ;
}
public void performWorkOnDb() throws Exception {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
progress.set(1.0*i / 100);
}
}
}
现在在您的 Task
中,您可以观察到 属性 并更新任务的进度:
Service<Void> myService = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
try {
DatabaseFunctionality dbFunc = new DatabaseFunctionality();
dbFunc.progressProperty().addListener((obs, oldProgress, newProgress) ->
updateProgress(newProgress.doubleValue(), 1));
dbaseFunc.performWorkOnDb();
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
另一种选择(如果您不希望数据访问对象依赖于 JavaFX 属性 API)是向数据访问对象传递回调以更新进度。 BiConsumer<Integer, Integer>
适用于此:
public class DatabaseFunctionality {
private BiConsumer<Integer, Integer> progressUpdate ;
public void setProgressUpdate(BiConsumer<Integer, Integer> progressUpdate) {
this.progressUpdate = progressUpdate ;
}
public void performWorkOnDb() throws Exception {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
if (progressUpdate != null) {
progressUpdate.accept(i, 100);
}
}
}
}
然后
Service<Void> myService = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
try {
DatabaseFunctionality dbFunc = new DatabaseFunctionality();
dbFunc.setProgressUpdate((workDone, totalWork) ->
updateProgress(workDone, totalWork));
dbaseFunc.performWorkOnDb();
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
public void initialize() {
Task<Void> task = new Task<>() {
@Override
protected Void call() {
try {
Double d = 0.0;
for (int i = 1; i <= 100; i++) {
Thread.sleep(100);
d = 1.0 * i / 100;
updateProgress(d, 1);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
};
task.progressProperty().addListener((obs, oldProgress, newProgress) -> {
System.out.println((newProgress.doubleValue() * 100) + "% completed");
});
new Thread(task).start();
}
在 JavaFX 应用程序中,我希望根据我在另一个 class 中实现的一些工作逻辑来更新状态栏。
我不知道如何将我希望将工作逻辑传递给方法(而不是将其写在任务中)与了解工作进度百分比相结合。
这是带有任务的控制器示例:
public class FXMLDocumentController implements Initializable {
@FXML private Label label;
@FXML ProgressBar progressBar;
@FXML
private void handleButtonAction(ActionEvent event) {
Service<Void> myService = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
try {
DatabaseFunctionality.performWorkOnDb();
//updateProgress(1, 1);
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
progressBar.progressProperty().bind(myService.progressProperty());
myService.restart();
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
这是帮手class:
public class DatabaseFunctionality {
public static void performWorkOnDb () throws InterruptedException {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
//Update progress
}
}
}
谢谢
这里有几个选项。一种是按照 Uluk 的建议去做,并在你的 DatabaseFunctionality
class:
public class DatabaseFunctionality {
private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper();
public double getProgress() {
return progressProperty().get();
}
public ReadOnlyDoubleProperty progressProperty() {
return progress ;
}
public void performWorkOnDb() throws Exception {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
progress.set(1.0*i / 100);
}
}
}
现在在您的 Task
中,您可以观察到 属性 并更新任务的进度:
Service<Void> myService = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
try {
DatabaseFunctionality dbFunc = new DatabaseFunctionality();
dbFunc.progressProperty().addListener((obs, oldProgress, newProgress) ->
updateProgress(newProgress.doubleValue(), 1));
dbaseFunc.performWorkOnDb();
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
另一种选择(如果您不希望数据访问对象依赖于 JavaFX 属性 API)是向数据访问对象传递回调以更新进度。 BiConsumer<Integer, Integer>
适用于此:
public class DatabaseFunctionality {
private BiConsumer<Integer, Integer> progressUpdate ;
public void setProgressUpdate(BiConsumer<Integer, Integer> progressUpdate) {
this.progressUpdate = progressUpdate ;
}
public void performWorkOnDb() throws Exception {
for (int i = 1; i <= 100; i++) {
System.out.println("i=" + i);
Thread.sleep(100);
if (progressUpdate != null) {
progressUpdate.accept(i, 100);
}
}
}
}
然后
Service<Void> myService = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
try {
DatabaseFunctionality dbFunc = new DatabaseFunctionality();
dbFunc.setProgressUpdate((workDone, totalWork) ->
updateProgress(workDone, totalWork));
dbaseFunc.performWorkOnDb();
} catch (InterruptedException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
public void initialize() {
Task<Void> task = new Task<>() {
@Override
protected Void call() {
try {
Double d = 0.0;
for (int i = 1; i <= 100; i++) {
Thread.sleep(100);
d = 1.0 * i / 100;
updateProgress(d, 1);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
};
task.progressProperty().addListener((obs, oldProgress, newProgress) -> {
System.out.println((newProgress.doubleValue() * 100) + "% completed");
});
new Thread(task).start();
}