获取所有JavaFX任务的列表

时间:2014-03-08 19:52:48

标签: javafx javafx-2 javafx-8

有没有办法在JavaFX应用程序中获取所有正在运行的任务和服务?

我想在列表中显示正在运行的任务。

2 个答案:

答案 0 :(得分:4)

布莱恩的答案是要走的路。如果您有多个位置正在创建任务,那么管理可能会有点棘手。以下显示了将所有内容封装到Executor实现中的方法。请注意,我仍然按照brian的建议完成:将任务添加到列表并在完成后删除它们;我只是在Executor中管理它,以便修改列表的代码都在一个地方。

MonitoringExecutor.java:

import java.util.concurrent.Executor;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;


/**
 * Wraps an Executor and exposes an ObservableList of Workers which have been
 * executed but have not completed. (Workers are considered completed if they 
 * exit a RUNNING state; i.e. they are in a SUCCEEDED, FAILED, or CANCELLED state.)
 *
 */
public class MonitoringExecutor implements Executor {
    private final Executor exec ;
    private final ObservableList<Worker<?>> taskList ;
    public MonitoringExecutor(Executor exec) {
        this.exec = exec;
        this.taskList = FXCollections.observableArrayList();
    }
    @Override
    public void execute(Runnable command) {
        if (command instanceof Worker) {
            final Worker<?> task = (Worker<?>) command ;
            task.stateProperty().addListener(new ChangeListener<State>() {
                @Override
                public void changed(ObservableValue<? extends State> obs,
                        State oldState, State newState) {
                    if (oldState == State.RUNNING) {
                        taskList.remove(task);
                    }
                }
            });
            taskList.add(task);
        }
        exec.execute(command);
    }
    public ObservableList<Worker<?>> getWorkerList() {
        return taskList;
    }

}

以下是使用它的一个例子:

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TaskMonitor extends Application {

    @Override
    public void start(Stage primaryStage) {
        final IntegerProperty tasksCreated = new SimpleIntegerProperty(0);

        final ThreadFactory threadFactory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setDaemon(true);
                return t;
            }
        };
        final MonitoringExecutor exec = new MonitoringExecutor(Executors.newFixedThreadPool(5, threadFactory));

        final TableView<Worker<?>> taskTable = createTable();
        taskTable.setItems(exec.getWorkerList());

        final Button newTaskButton = new Button();
        newTaskButton.textProperty().bind(Bindings.format("Create task %d", tasksCreated.add(1)));
        newTaskButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                tasksCreated.set(tasksCreated.get()+1);
                exec.execute(new CountingTask("Task "+tasksCreated.get()));
            }
        });

        final BorderPane root = new BorderPane();
        root.setCenter(taskTable);
        final HBox controls = new HBox();
        controls.setPadding(new Insets(10));
        controls.setAlignment(Pos.CENTER);
        controls.getChildren().add(newTaskButton);
        root.setBottom(controls);

        final Scene scene = new Scene(root, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TableView<Worker<?>> createTable() {
        final TableView<Worker<?>> taskTable = new TableView<>();
        final TableColumn<Worker<?>, String> titleCol = new TableColumn<>("Title");
        titleCol.setCellValueFactory(new PropertyValueFactory<Worker<?>, String>("title"));
        final TableColumn<Worker<?>, Double> progressCol = new TableColumn<>("Progress");
        progressCol.setCellValueFactory(new PropertyValueFactory<Worker<?>, Double>("progress"));
        progressCol.setCellFactory(new Callback<TableColumn<Worker<?>, Double>, TableCell<Worker<?>, Double>>() {

            @Override
            public TableCell<Worker<?>, Double> call(TableColumn<Worker<?>, Double> col) {
                return new ProgressTabelCell();
            }

        });
        final TableColumn<Worker<?>, State> stateCol = new TableColumn<>("State");
        stateCol.setCellValueFactory(new PropertyValueFactory<Worker<?>, State>("state"));
        final TableColumn<Worker<?>, String> messageCol = new TableColumn<>("Message");
        messageCol.setCellValueFactory(new PropertyValueFactory<Worker<?>, String>("message"));
        messageCol.setPrefWidth(200);
        taskTable.getColumns().addAll(Arrays.asList(titleCol, progressCol, stateCol, messageCol));
        return taskTable;
    }

    private static class CountingTask extends Task<Void> {

        private CountingTask(String title) {
            updateTitle(title);
        }

        @Override
        protected Void call() throws Exception {
            final int n = new Random().nextInt(100)+100;
            for (int i=0; i<n; i++) {
                updateProgress(i, n);
                updateMessage(String.format("Count is %d (of %d)", i, n));
                Thread.sleep(100);
            }
            return null;
        }
    }

    private static class ProgressTabelCell extends TableCell<Worker<?>, Double> {
        final ProgressBar progressBar = new ProgressBar();

        @Override
        public void updateItem(Double value, boolean empty) {
           if (empty || value == null) {
               setGraphic(null);
           } else {
               setGraphic(progressBar);
               progressBar.setProgress(value);
           }
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

答案 1 :(得分:2)

只需根据需要在列表中添加和删除它们即可。然后你可以在列表中显示它们。这是一些代码。

ObservableList<String> runningTasks;

runningTasks.add(task.getTitle());
new Thread(task).start();

task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
    @Override
    public void handle(WorkerStateEvent event) {
        runningTasks.remove(task.getTitle());
    }});