有没有办法在JavaFX中绑定ListProperty的内容?

Rya*_*n J 2 javafx-8

是否存在绑定内容的现有方法ListProperty?考虑以下:

private final ListProperty<Worker<?>> workers = new SimpleListProperty<>(FXCollections.observableArrayList());
public ListProperty<Worker<?>> workersProperty() {return workers;}
public ObservableList<Worker<?>> getWorkers() {return workers.get();}
public void setWorkers(ObservableList<Worker<?>> workers) {this.workers.set(workers);}

private final ObservableList<Worker<?>> stateWatchedWorkers = FXCollections.observableArrayList(
        new Callback<Worker<?>, Observable[]>() {
            @Override
            public Observable[] call(final Worker<?> param) {
                return new Observable[]{
                        param.stateProperty()
                };
            }
        }
);
Run Code Online (Sandbox Code Playgroud)

我想要做的是将stateWatchedWorkers列表的内容绑定到工作人员.如果workers替换整个列表,我希望stateWatchedWorkers更新以匹配新列表的内容.换句话说,我希望stateWatchedWorkers列表映射到workers属性所持有的当前列表.

Jam*_*s_D 6

你可以做

Bindings.bindContent(stateWatchedWorkers, workers);
Run Code Online (Sandbox Code Playgroud)

(因为ListProperty<T>实现ObservableList<T>,通过将ObservableList方法委托给包装列表等).

这是一个完整的例子:

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class ListContentBindingExample extends Application {

    private static final Random RNG = new Random();
    private static final ExecutorService exec = Executors.newFixedThreadPool(5, r -> {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t ;
    });

    @Override
    public void start(Stage primaryStage) {
        final ListProperty<Worker<?>> workers = new SimpleListProperty<>(FXCollections.observableArrayList());

        final ObservableList<Worker<?>> stateWatchedWorkers = FXCollections.observableArrayList(worker -> new Observable[] { worker.stateProperty() });
        Bindings.bindContent(stateWatchedWorkers, workers);

        Button newWorker = new Button("New Worker") ;
        newWorker.setOnAction(event -> workers.add(createTask()));

        Button replaceAllWorkers = new Button("New Worker List");
        replaceAllWorkers.setOnAction(event -> {
            ObservableList<Worker<?>> newWorkers = FXCollections.observableArrayList();
            for (int i=0; i<=10; i++) {
                newWorkers.add(createTask());
            }
            workers.set(newWorkers);
        });

        ListView<Worker<?>> workerView = new ListView<>();
        workerView.setCellFactory(listView -> new ListCell<Worker<?>>() {
            @Override
            public void updateItem(Worker<?> worker, boolean empty) {
                super.updateItem(worker, empty);
                if (empty) {
                    setText(null);
                } else {
                    setText(worker.getState().toString());
                }
            }
        });
        workerView.setItems(stateWatchedWorkers);

        workers.get().addListener((Change<? extends Worker<?>> change) -> stateWatchedWorkers.forEach(w -> System.out.println(w.getState())));
        stateWatchedWorkers.addListener((Change<? extends Worker<?>> change) -> stateWatchedWorkers.forEach(w -> System.out.println(w.getState())));

        HBox buttons = new HBox(5, newWorker, replaceAllWorkers);
        buttons.setAlignment(Pos.CENTER);
        buttons.setPadding(new Insets(10));

        primaryStage.setScene(new Scene(new BorderPane(workerView, null, null, buttons, null), 250, 400));
        primaryStage.show();
    }

    private Worker<Void> createTask() {
        Service<Void> service = new Service<Void>() {

            @Override
            protected Task<Void> createTask() {
                return new Task<Void>() {
                    @Override
                    public Void call() throws Exception {
                        Thread.sleep(1000 + RNG.nextInt(2000));
                        return null ;
                    }
                };
            }

        };

        service.setExecutor(exec);
        service.start();
        return service ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)