ドキュメント



JavaFX: JavaFX UIコンポーネントの操作

16 コンボ・ボックス

この章では、JavaFXアプリケーションでコンボ・ボックスを使用する方法について説明します。ここでは編集可能、および編集不可のコンボ・ボックスについて説明し、編集可能なコンボ・ボックスでの変更の追跡方法とそのイベントの処理方法について学習し、コンボ・ボックスのデフォルトの実装に代わるセル・ファクトリの使用方法について説明します。

コンボ・ボックスは、ユーザーが複数のオプションから1つを選択できるユーザー・インタフェースの一般的な要素です。コンボ・ボックスは選択ボックスとは異なり、ドロップダウン・リストにスクロールを追加できるため、表示する項目の数が一定の制限を超える場合に役立ちます。項目の数が特定の制限を超えていない場合、開発者はコンボ・ボックスと選択ボックスのどちらがニーズに一致するかを判断する必要があります。

JavaFXアプリケーションでコンボ・ボックスを作成するには、JavaFX APIのComboBoxクラスを使用します。図16-1に、2つのコンボ・ボックスのあるアプリケーションを示します。

図16-1 2つのコンボ・ボックスのあるアプリケーション

図16-1の説明が続きます
「図16-1 2つのコンボ・ボックスのあるアプリケーション」の説明

コンボ・ボックスの作成

コンボ・ボックスを作成する場合、ChoiceBoxListView、およびTableViewなど、他のUIコントロールと同様に、ComboBoxクラスをインスタンス化し、項目を監視可能リストとして定義する必要があります。例16-1では、コンストラクタ内に項目を設定します。

例16-1 監視可能なリストを使用したコンボ・ボックスの作成

ObservableList<String> options = 
    FXCollections.observableArrayList(
        "Option 1",
        "Option 2",
        "Option 3"
    );
final ComboBox comboBox = new ComboBox(options);

その他の選択肢としては、空のコンストラクタを使用して、それにsetItemsメソッドをcomboBox.setItems(options);のようにコールしてコンボ・ボックスを作成します。

コンボ・ボックスがアプリケーション・シーンに追加されると、図16-2に示すようにユーザー・インタフェースに表示されます。

図16-2 3つの項目のあるコンボ・ボックス

図16-2の説明が続きます
「図16-2 3つの項目のあるコンボ・ボックス」の説明

項目のリストには、常に新しい値を追加できます。例16-2では、3つの項目をcomboBoxコントロールに追加してこのタスクを実装しています。

例16-2 コンボ・ボックスへの項目の追加

comboBox.getItems().addAll(
    "Option 4",
    "Option 5",
    "Option 6"
);

ComboBoxクラスはこのコンボ・ボックスで使用できる簡単なプロパティとメソッドを提供します。

setValueメソッドを使用すると、コンボ・ボックスで選択された項目を指定できます。ComboBoxオブジェクトにsetValueメソッドをコールすると、selectionModelプロパティで選択された項目は、値がコンボ・ボックス項目のリストになくても、その値に変更されます。次に、この値を含むよう項目リストが変更されると、該当する項目が選択されます。

同様に、getValueメソッドをコールすると、選択された項目の値を取得できます。ユーザーが項目を選択すると、selectionModelプロパティの選択された項目とコンボ・ボックスのvalueプロパティの両方が新しい値に更新されます。

行を表示する場合は、ComboBoxドロップダウン・リストに表示可能な行数を制限することもできます。comboBoxコントロールで3つの項目の表示を可能にするには、次のコード行comboBox.setVisibleRowCount(3)を使用します。このメソッドをコールした結果、図16-3に示すように、表示可能な行は3行に制限され、スクロール・バーが表示されます。

図16-3 コンボ・ボックスに表示可能な行数の設定

図16-3の説明が続きます
「図16-3 コンボ・ボックスに表示可能な行数の設定」の説明

ComboBoxクラスには一般的な表記法があり、様々なタイプの項目へのユーザーによるデータ移入を有効にできますが、Node、またはその他のサブクラスはタイプとして使用しないでください。シーン・グラフの概念では、アプリケーション・シーンの1つの場所に配置できるNodeオブジェクトは1つのみであるとされているため、選択された項目は、項目のComboBoxリストから削除されます。選択を変更すると、最初に選択していた項目がリストに戻され、新しい選択が削除されます。この状況を防止するには、セル・ファクトリ・メカニズムとAPIドキュメントに記載されているソリューションを使用します。セル・ファクトリのメカニズムは、ComboBoxオブジェクトの初期の動作または外観を変更する必要がある場合に特に役立ちます。

ComboBoxSampleアプリケーションは、一般的な電子メール・インタフェースでコンボ・ボックスを使用する方法を示すよう設計されています。例16-3では、このようなインタフェースを作成し、2つのコンボ・ボックスを使用して電子メールの受信者とメッセージの優先度を選択できるようにします。

例16-3 コンボ・ボックスの作成およびシーンへの追加

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
 
public class ComboBoxSample extends Application {
    public static void main(String[] args) {
        launch(args);
    }
        
    final Button button = new Button ("Send");
    final Label notification = new Label ();
    final TextField subject = new TextField("");
    final TextArea text = new TextArea ("");
    
    String address = " ";
    
    @Override public void start(Stage stage) {
        stage.setTitle("ComboBoxSample");
        Scene scene = new Scene(new Group(), 500, 270);
        
        final ComboBox emailComboBox = new ComboBox();
        emailComboBox.getItems().addAll(
            "jacob.smith@example.com",
            "isabella.johnson@example.com",
            "ethan.williams@example.com",
            "emma.jones@example.com",
            "michael.brown@example.com"  
        );
        
        final ComboBox priorityComboBox = new ComboBox();
        priorityComboBox.getItems().addAll(
            "Highest",
            "High",
            "Normal",
            "Low",
            "Lowest" 
        );   

        priorityComboBox.setValue("Normal");
        
        GridPane grid = new GridPane();
        grid.setVgap(4);
        grid.setHgap(10);
        grid.setPadding(new Insets(5, 5, 5, 5));
        grid.add(new Label("To: "), 0, 0);
        grid.add(emailComboBox, 1, 0);
        grid.add(new Label("Priority: "), 2, 0);
        grid.add(priorityComboBox, 3, 0);
        grid.add(new Label("Subject: "), 0, 1);
        grid.add(subject, 1, 1, 3, 1);            
        grid.add(text, 0, 2, 4, 1);
        grid.add(button, 0, 3);
        grid.add (notification, 1, 3, 3, 1);
        
        Group root = (Group)scene.getRoot();
        root.getChildren().add(grid);
        stage.setScene(scene);
        stage.show();
    }    
}

例16-3に示すコンボ・ボックスは、どちらもgetItemsメソッドとaddAllメソッドを使用して項目を追加します。このコードをコンパイルして実行すると、図16-4に示すアプリケーション・ウィンドウが作成されます。

図16-4 電子メール受信者および優先度のコンボ・ボックス

図16-4の説明が続きます
「図16-4 電子メール受信者および優先度のコンボ・ボックス」の説明

編集可能なコンボ・ボックス

通常、電子メール・クライアント・アプリケーションでは、ユーザーはアドレス帳からの受信者の選択、および新しいアドレスの入力が可能です。このようなタスクには、編集可能なコンボ・ボックスが最も適しています。ComboBoxクラスのsetEditable(true)メソッドを使用して、コンボ・ボックスを編集可能にします。setPromptTextメソッドでは、何も選択されていないときにコンボ・ボックスの編集領域に表示するテキストを指定できます。例16-4では、アプリケーションの変更コードを確認します。太字の行が例16-3に追加された部分です。

例16-4 編集可能コンボ・ボックスに新たに入力された値の処理

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
 
public class ComboBoxSample extends Application {
        public static void main(String[] args) {
        launch(args);
    }
    
    final Button button = new Button ("Send");
    final Label notification = new Label ();
    final TextField subject = new TextField("");
    final TextArea text = new TextArea ("");
    
    String address = " ";
    
    @Override public void start(Stage stage) {
        stage.setTitle("ComboBoxSample");
        Scene scene = new Scene(new Group(), 500, 270);
        
        final ComboBox emailComboBox = new ComboBox();
        emailComboBox.getItems().addAll(
            "jacob.smith@example.com",
            "isabella.johnson@example.com",
            "ethan.williams@example.com",
            "emma.jones@example.com",
            "michael.brown@example.com"  
        );
        emailComboBox.setPromptText("Email address");
        emailComboBox.setEditable(true);        
        emailComboBox.setOnAction((Event ev) -> {
            address = 
                emailComboBox.getSelectionModel().getSelectedItem().toString();    
        });
        
        final ComboBox priorityComboBox = new ComboBox();
        priorityComboBox.getItems().addAll(
            "Highest",
            "High",
            "Normal",
            "Low",
            "Lowest" 
        );   

        priorityComboBox.setValue("Normal");
     
        button.setOnAction((ActionEvent e) -> {
            if (emailComboBox.getValue() != null && 
                    !emailComboBox.getValue().toString().isEmpty()){
                notification.setText("Your message was successfully sent"
                        + " to " + address);
                emailComboBox.setValue(null);
                if (priorityComboBox.getValue() != null &&
                        !priorityComboBox.getValue().toString().isEmpty()){
                    priorityComboBox.setValue(null);
                }
                subject.clear();
                text.clear();
            }
            else {
                notification.setText("You have not selected a recipient!");
            }
        });

        GridPane grid = new GridPane();
        grid.setVgap(4);
        grid.setHgap(10);
        grid.setPadding(new Insets(5, 5, 5, 5));
        grid.add(new Label("To: "), 0, 0);
        grid.add(emailComboBox, 1, 0);
        grid.add(new Label("Priority: "), 2, 0);
        grid.add(priorityComboBox, 3, 0);
        grid.add(new Label("Subject: "), 0, 1);
        grid.add(subject, 1, 1, 3, 1);            
        grid.add(text, 0, 2, 4, 1);
        grid.add(button, 0, 3);
        grid.add (notification, 1, 3, 3, 1);
        
        Group root = (Group)scene.getRoot();
        root.getChildren().add(grid);
        stage.setScene(scene);
        stage.show();
    }
}

emailComboBoxを編集できる他に、このコード・フラグメントはこのコントロールのイベント処理を実装します。新たに入力、または選択した値はaddress変数に格納されます。ユーザーが「Send」ボタンを押すと、電子メール・アドレスを含む通知が表示されます。

図16-5は、ユーザーがJacob Smithの電子メール・アドレスを編集し、これをgreg.smith@example.comに変更した瞬間のキャプチャを示します。

図16-5 電子メール・アドレスの編集

図16-5の説明が続きます
「図16-5 電子メール・アドレスの編集」の説明

「Send」ボタンを押すと、すべてのコントロールがデフォルトの状態に戻ります。TextFieldオブジェクトとTextAreaオブジェクトに対してclearメソッドがコールされ、コンボ・ボックスの選択された項目にnull値が設定されます。図16-6に、「Send」ボタンを押した後の瞬間を示します。

図16-6 「Send」ボタンを押した後のユーザー・インタフェース

図16-6の説明が続きます
「図16-6 「Send」ボタンを押した後のユーザー・インタフェース」の説明

コンボ・ボックスへのセル・ファクトリの適用

セル・ファクトリのメカニズムを使用すると、コンボ・ボックスのデフォルトの動作または外観を変更できます。例16-5では、セル・ファクトリを作成し、それを「Priority」コンボ・ボックスに適用して、優先度タイプを特別な色で強調表示します。

例16-5 「Priority」コンボ・ボックスへのセル・ファクトリの実装

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
 
public class ComboBoxSample extends Application {
        public static void main(String[] args) {
        launch(args);
    }
    
    final Button button = new Button ("Send");
    final Label notification = new Label ();
    final TextField subject = new TextField("");
    final TextArea text = new TextArea ("");
    
    String address = " ";
    
    @Override public void start(Stage stage) {
        stage.setTitle("ComboBoxSample");
        Scene scene = new Scene(new Group(), 500, 270);
        
        final ComboBox emailComboBox = new ComboBox();
        emailComboBox.getItems().addAll(
            "jacob.smith@example.com",
            "isabella.johnson@example.com",
            "ethan.williams@example.com",
            "emma.jones@example.com",
            "michael.brown@example.com"  
        );
        emailComboBox.setPromptText("Email address");
        emailComboBox.setEditable(true);        
        emailComboBox.setOnAction((Event ev) -> {
            address = 
                emailComboBox.getSelectionModel().getSelectedItem().toString();    
        });
        
        final ComboBox priorityComboBox = new ComboBox();
        priorityComboBox.getItems().addAll(
            "Highest",
            "High",
            "Normal",
            "Low",
            "Lowest" 
        );   

        priorityComboBox.setValue("Normal");
        priorityComboBox.setCellFactory(
            new Callback<ListView<String>, ListCell<String>>() {
                @Override public ListCell<String> call(ListView<String> param) {
                    final ListCell<String> cell = new ListCell<String>() {
                        {
                            super.setPrefWidth(100);
                        }    
                        @Override public void updateItem(String item, 
                            boolean empty) {
                                super.updateItem(item, empty);
                                if (item != null) {
                                    setText(item);    
                                    if (item.contains("High")) {
                                        setTextFill(Color.RED);
                                    }
                                    else if (item.contains("Low")){
                                        setTextFill(Color.GREEN);
                                    }
                                    else {
                                        setTextFill(Color.BLACK);
                                    }
                                }
                                else {
                                    setText(null);
                                }
                            }
                };
                return cell;
            }
        });
     
        button.setOnAction((ActionEvent e) -> {
            if (emailComboBox.getValue() != null && 
                    !emailComboBox.getValue().toString().isEmpty()){
                notification.setText("Your message was successfully sent"
                        + " to " + address);
                emailComboBox.setValue(null);
                if (priorityComboBox.getValue() != null &&
                        !priorityComboBox.getValue().toString().isEmpty()){
                    priorityComboBox.setValue(null);
                }
                subject.clear();
                text.clear();
            }
            else {
                notification.setText("You have not selected a recipient!");
            }
        })
        
        GridPane grid = new GridPane();
        grid.setVgap(4);
        grid.setHgap(10);
        grid.setPadding(new Insets(5, 5, 5, 5));
        grid.add(new Label("To: "), 0, 0);
        grid.add(emailComboBox, 1, 0);
        grid.add(new Label("Priority: "), 2, 0);
        grid.add(priorityComboBox, 3, 0);
        grid.add(new Label("Subject: "), 0, 1);
        grid.add(subject, 1, 1, 3, 1);            
        grid.add(text, 0, 2, 4, 1);
        grid.add(button, 0, 3);
        grid.add (notification, 1, 3, 3, 1);
        
        Group root = (Group)scene.getRoot();
        root.getChildren().add(grid);
        stage.setScene(scene);
        stage.show();
 
    }    
}

セル・ファクトリはListCellオブジェクトを作成します。すべてのセルが単一のコンボ・ボックス項目と関連付けられます。各コンボ・ボックス項目の幅は、setPrefWidthメソッドを使用して設定します。updateItemメソッドは、「High」および「Highest」の項目に対しては赤、「Low」および「Lowest」の項目に対しては緑に設定し、「Normal」の項目に対しては黒のままで設定を変更しません。

図16-7 は、例16-5を適用した後の「Priority」コンボ・ボックスの項目を示しています。

図16-7 変更後の「Priority」コンボ・ボックス

図16-7の説明が続きます
「図16-7 変更後の「Priority」コンボ・ボックス」の説明

ComboBoxコントロールの外観は、CSSスタイルや視覚効果を適用してさらに拡張できます。

関連APIドキュメント

ウィンドウを閉じる

目次

JavaFX: JavaFX UIコンポーネントの操作

展開 | 縮小