2

サービスを使用してJavaFX2.2UIのテキストフィールドのセットを更新する方法を理解しようとしていますが、ドキュメントにはこれに関するサンプルやヒントはありません。AddressbookとEnsembleの両方のサンプルはテーブルを扱います。サービスは文字列のObservableListを返します。どのようにバインディングを行いますか?

textField0 <---> observableList [0]

textField1 <---> observableList [1]

ServiceSample(同時実行|サービスサンプル(http://download.oracle.com/otndocs/products/javafx/2.2/samples/Ensemble/index.html))を変更して、TextFieldsのListViewを作成しましたが、その方法がわかりません。バインディング。代わりに何を置くべきか

tableView.itemsProperty().bind(service.valueProperty());

この行はコンパイルすらしません:

listView.itemsProperty().bind(service.valueProperty()); 

変更された並行性| http://download.oracle.com/otndocs/products/javafx/2.2/samples/Ensemble/index.htmlのサービスサンプル

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.Date;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;

/**
 * A sample showing use of a Service to retrieve data in a background thread.
 * Selecting the Refresh button restarts the Service.
 *
 * @see javafx.collections.FXCollections
 * @see javafx.concurrent.Service
 * @see javafx.concurrent.Task
 * @see javafx.scene.control.ProgressIndicator
 * @see javafx.scene.control.TableColumn
 * @see javafx.scene.control.TableView
 */
public class ServiceSample extends Application {

    final GetDailySalesService service = new GetDailySalesService();

    private void init(Stage primaryStage) {
        Group root = new Group();
        primaryStage.setScene(new Scene(root));

        VBox vbox = new VBox(5);
        vbox.setPadding(new Insets(12));
        ListView<TextField> listView = new ListView<TextField>();
        Button button = new Button("Refresh");
        button.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent t) {
                service.restart();
            }
        });
        vbox.getChildren().addAll( listView, button);

        Region veil = new Region();
        veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
        ProgressIndicator p = new ProgressIndicator();
        p.setMaxSize(150, 150);

        p.progressProperty().bind(service.progressProperty());
        veil.visibleProperty().bind(service.runningProperty());
        p.visibleProperty().bind(service.runningProperty());
        // what to put here ? tableView.itemsProperty().bind(service.valueProperty());

        StackPane stack = new StackPane();
        stack.getChildren().addAll(vbox, veil, p);

        root.getChildren().add(stack);
        service.start();
    }

    /**
     * A service for getting the DailySales data. This service exposes an
     * ObservableList for convenience when using the service. This
     * <code>results</code> list is final, though its contents are replaced when
     * a service call successfully concludes.
     */
    public class GetDailySalesService extends Service<ObservableList<String>> {

        /**
         * Create and return the task for fetching the data. Note that this
         * method is called on the background thread (all other code in this
         * application is on the JavaFX Application Thread!).
         *
         * @return A task
         */
        @Override
        protected Task createTask() {
            return new GetDailySalesTask();
        }
    }

    public class GetDailySalesTask extends Task<ObservableList<String>> {       
        @Override protected ObservableList<String> call() throws Exception {
            for (int i = 0; i < 500; i++) {
                updateProgress(i, 500);
                Thread.sleep(5);
            }
            ObservableList<String> sales = FXCollections.observableArrayList();
            sales.add(new String("A1"));
            sales.add(new String("A2"));
            return sales;
        }
    }

    @Override public void start(Stage primaryStage) throws Exception {
        init(primaryStage);
        primaryStage.show();
    }
    public static void main(String[] args) { launch(args); }
}
4

2 に答える 2

3

この回答は、バインドを使用してサービスからJavaFX2TextFieldのセットを更新する方法を示しています。答えの基本は、質問に投稿された元のサンプルコードです。ListView(Strings)の値のタイプが、サービスから返される値のタイプと一致するようになったため、更新は機能します。

元のコードに、次の変更を加えます。

変化する:

ListView<TextField> listView = new ListView<TextField>();

に:

ListView<String> listView = new ListView<String>();

変化する:

// what to put here ? tableView.itemsProperty().bind(service.valueProperty());

に:

listView.itemsProperty().bind(service.valueProperty());

これで、listViewはサービスの結果に基づいて更新されます(変更を示すために、固定データを使用するのではなく、サービスタスクにランダムなデータを追加できます)。

これで、入ってくるリストの値に基づいてデータが更新されるListViewができました。ただし、静的ラベルのリストではなく、TextFieldsのリストが必要です。TextFieldsをListViewに取り込むには、独自のセルファクトリを作成する必要があります。

これが元の例の更新です。この更新により、TextFieldの作成を処理するためのセルファクトリがいくつか提供されます。InstantEditingCellは、すべてのアイテムのTextFieldを作成します。ClickableEditingCellは、アイテムをクリックするとセルを作成します(そのクラスのコードは、JavaFX TableViewサンプルドキュメントのEditingCellからコピーされました)。

import java.util.Random;
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.util.Callback;

/**
 * A sample showing use of a Service to retrieve data in a background thread.
 * Selecting the Refresh button restarts the Service.
 *
 * @see javafx.collections.FXCollections
 * @see javafx.concurrent.Service
 * @see javafx.concurrent.Task
 * @see javafx.scene.control.ProgressIndicator
 * @see javafx.scene.control.TableColumn
 * @see javafx.scene.control.TableView
 */
public class ServiceSample extends Application {

    final GetDailySalesService service = new GetDailySalesService();
    final Random random = new Random();

    private void init(Stage primaryStage) {
        Group root = new Group();
        primaryStage.setScene(new Scene(root));

        VBox vbox = new VBox(5);
        vbox.setPadding(new Insets(12));
        ListView<String> listView = new ListView<>();
        listView.setEditable(true);
        Button button = new Button("Refresh");
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent t) {
                service.restart();
            }
        });
        listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
            @Override public ListCell<String> call(ListView<String> param) {
                return new InstantEditingCell();
            }
        });
        listView.setPrefHeight(200);
        vbox.getChildren().addAll( listView, button);

        Region veil = new Region();
        veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
        ProgressIndicator p = new ProgressIndicator();
        p.setMaxSize(150, 150);

        p.progressProperty().bind(service.progressProperty());
        veil.visibleProperty().bind(service.runningProperty());
        p.visibleProperty().bind(service.runningProperty());
        listView.itemsProperty().bind(service.valueProperty());

        StackPane stack = new StackPane();
        stack.getChildren().addAll(vbox, veil, p);

        root.getChildren().add(stack);
        service.start();
    }

    /**
     * A service for getting the DailySales data. This service exposes an
     * ObservableList for convenience when using the service. This
     * <code>results</code> list is final, though its contents are replaced when
     * a service call successfully concludes.
     */
    public class GetDailySalesService extends Service<ObservableList<String>> {

        /**
         * Create and return the task for fetching the data. Note that this
         * method is called on the background thread (all other code in this
         * application is on the JavaFX Application Thread!).
         *
         * @return A task
         */
        @Override
        protected Task createTask() {
            return new GetDailySalesTask();
        }
    }

    public class GetDailySalesTask extends Task<ObservableList<String>> {       
        @Override protected ObservableList<String> call() throws Exception {
            for (int i = 0; i < 500; i++) {
                updateProgress(i, 500);
                Thread.sleep(5);
            }
            ObservableList<String> sales = FXCollections.observableArrayList();
            sales.add("A1: " + random.nextInt());
            sales.add("A2: " + random.nextInt());
            return sales;
        }
    }

    @Override public void start(Stage primaryStage) throws Exception {
        init(primaryStage);
        primaryStage.show();
    }
    public static void main(String[] args) { launch(args); }

    class InstantEditingCell extends ListCell<String> {
        @Override public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);

            if (empty) {
                setGraphic(null);
            } else {
                final TextField textField = new TextField(getString());
                textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
                textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
                    @Override public void changed(ObservableValue<? extends Boolean> value, Boolean wasFocused, Boolean isFocused) {
                        if (!isFocused) {
                            commitEdit(textField.getText());
                        }
                    }
                });
                setGraphic(textField);
            }
        }

        private String getString() {
            return getItem() == null ? "" : getItem().toString();
        }
    }

    class ClickableEditingCell extends ListCell<String> {

        private TextField textField;

        public ClickableEditingCell() {
        }

        @Override
        public void startEdit() {
            if (!isEmpty()) {
                super.startEdit();
                createTextField();
                setText(null);
                setGraphic(textField);
                textField.selectAll();
            }
        }

        @Override
        public void cancelEdit() {
            super.cancelEdit();

            setText((String) getItem());
            setGraphic(null);
        }

        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);

            if (empty) {
                setText(null);
                setGraphic(null);
            } else {
                if (isEditing()) {
                    if (textField != null) {
                        textField.setText(getString());
                    }
                    setText(null);
                    setGraphic(textField);
                } else {
                    setText(getString());
                    setGraphic(null);
                }
            }
        }

        private void createTextField() {
            textField = new TextField(getString());
            textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
            textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
                @Override public void changed(ObservableValue<? extends Boolean> arg0, 
                    Boolean arg1, Boolean arg2) {
                        if (!arg2) {
                            commitEdit(textField.getText());
                        }
                }
            });
        }

        private String getString() {
            return getItem() == null ? "" : getItem().toString();
        }
    }

}

TextFieldsは静的オブジェクトではなく編集可能なオブジェクトであるため、元のデータの元の場所に編集をコミットするための何らかの方法も検討する必要があります。

サンプルプログラム出力:

テキストフィールドリスト

于 2012-10-31T23:51:55.260 に答える
0

このソートは機能しましたが、TextFieldのリストをサービスの出力にバインドする「自動」方法はありません。

import java.lang.String;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.List;
import java.util.ListIterator;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;

/**
 * A sample showing use of a Service to retrieve data in a background thread.
 * Selecting the Refresh button restarts the Service.
 *
 * @see javafx.collections.FXCollections
 * @see javafx.concurrent.Service
 * @see javafx.concurrent.Task
 * @see javafx.scene.control.ProgressIndicator
 * @see javafx.scene.control.TableColumn
 * @see javafx.scene.control.TableView
 */
public class ServiceSample extends Application {

    final GetDailySalesService service = new GetDailySalesService();

    private void init(Stage primaryStage) {
        Group root = new Group();
        primaryStage.setScene(new Scene(root));

        final VBox vbox = new VBox(5);
        vbox.setPadding(new Insets(12));

        Button button = new Button("Refresh");
        button.setOnAction(new EventHandler<ActionEvent>() {

            public void handle(ActionEvent t) {
                service.restart();
            }
        });
        TextField tf1, tf2, tf3;
        tf1 = new TextField();
        tf1.setId("0");
        tf2 = new TextField();
        tf2.setId("1");
        tf3 = new TextField();
        tf3.setId("2");        
        vbox.getChildren().addAll(tf1,tf2,tf3,button);

        Region veil = new Region();
        veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
        ProgressIndicator p = new ProgressIndicator();
        p.setMaxSize(150, 150);

        p.progressProperty().bind(service.progressProperty());
        veil.visibleProperty().bind(service.runningProperty());
        p.visibleProperty().bind(service.runningProperty()); 
        StackPane stack = new StackPane();
        stack.getChildren().addAll(vbox, veil, p);

        root.getChildren().add(stack);
            service.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent t) {
                System.out.println("done:" + t.getSource().getValue());
                List list = service.valueProperty().getValue();
                String[] sa = (String[]) list.toArray(new String[0]);
                for(int i=0; i<sa.length;i++) {
                    TextField tf = (TextField) vbox.lookup("#"+i);
                    tf.setText(sa[i]);
                }
            }
        });
        service.start();
    }

    /**
     * A service for getting the DailySales data. This service exposes an
     * ObservableList for convenience when using the service. This
     * <code>results</code> list is final, though its contents are replaced when
     * a service call successfully concludes.
     */
    public class GetDailySalesService extends Service<ObservableList<String>> {
        /**
         * Create and return the task for fetching the data. Note that this
         * method is called on the background thread (all other code in this
         * application is on the JavaFX Application Thread!).
         *
         * @return A task
         */
        @Override
        protected Task createTask() {
            return new GetDailySalesTask();
        }
    }

    public class GetDailySalesTask extends Task<ObservableList<String>> {       
        @Override protected ObservableList<String> call() throws Exception {
            for (int i = 0; i < 500; i++) {
                updateProgress(i, 500);
                Thread.sleep(5);
            }
            ObservableList<String> sales = FXCollections.observableArrayList();
            sales.add(new String("A1 " + System.currentTimeMillis()));
            sales.add(new String("A2 " + System.currentTimeMillis()));
            sales.add(new String("A3 " + System.currentTimeMillis()));
            return sales;
        }
    }

    @Override public void start(Stage primaryStage) throws Exception {
        init(primaryStage);
        primaryStage.show();
    }
    public static void main(String[] args) { launch(args); }
}
于 2012-10-31T22:05:01.410 に答える