リストや表など、一部のUIコントロールではセルのカスタマイズが可能になっている。セルをカスタマイズしたい場合は、Callbackインターフェースのcall関数をオーバーライドして戻り値をカスタマイズ後のセルとする。このCallbackインターフェースをsetCellFactory関数で登録することで、UIコントロール上にカスタマイズされたセルが表示される。カスタマイズできる代表的な操作を以下に示す。
- updateItem関数をオーバーロードし、セルの見た目を変更できる
- startEdit関数をオーバーロードし、セル編集開始時の動作を変更できる。commitEdit関数呼び出しで編集の確定、cancelEdit関数呼び出しで編集のキャンセルが可能
また、セルをカスタマイズできるUIコントロールは以下のとおり。
UIコントロール |
対応するセルのクラス |
DatePicker |
DateCell |
ComboBox |
ListCell |
ListView |
ListCell |
TreeView |
TreeCell |
TableView |
TableCell
TableRow |
TreeTableView |
TreeTableCell
TreeTableRow |
※ChoiceBoxはセルのカスタマイズ不可
■ セルのカスタマイズ・例1(見た目の変更)
以下に、セルをカスタマイズするためのサンプルプログラムを示す。サンプルではセルに画像を付与し、文字色を赤色にしている。
◇サンプルコード
package application_fx;
import java.io.File;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TestCellFactory extends Application {
public static void main(String[] args)
{
launch( args );
}
@Override
public void start(Stage primaryStage) throws Exception
{
// シーングラフを作成
VBox root = new VBox( 2.0 );
// コンボボックス
ComboBox<String> combo = new ComboBox<>();
combo.setItems( FXCollections.observableArrayList( "その1" , "その2" , "その3" ) );
combo.setEditable( true );
root.getChildren().add( combo );
// セル・ファクトリを作成
Callback<ListView<String>,ListCell<String>> cellFactory = p ->
{
// セルを作成
ListCell<String> cell = new ListCell<String>()
{
/**
* 描画関数
* @param item
* @param empty
*/
@Override public void updateItem( String item , boolean empty )
{
// 元関数を呼び出し
super.updateItem(item, empty);
// Null対策
if( item == null ){ return; }
// セルのプロパティを設定
// テキスト
setText(item);
setTextFill( Color.RED );
// 画像
String url = new File( "img/chara_one.png" ).toURI().toString();
Image img = new Image( url );
ImageView imgView = new ImageView( img );
imgView.setFitWidth( 16 );
imgView.setFitHeight( 16 );
setGraphic( imgView );
}
};
return cell;
};
combo.setCellFactory( cellFactory );
// シーンを作成
Scene scene = new Scene( root , 500 , 200 , Color.web( "9FCC7F" ) );
// ウィンドウ表示
primaryStage.setScene( scene );
primaryStage.show();
}
}
◇実行結果
◇解説
38行目~70行目でCellFactoryとして登録するCallBack関数を設定している。関数内部では、ListCell::updateItem関数をオーバーロードした匿名クラスを作成・インスタンス化している。
■ セルのカスタマイズ・例2(編集機能を追加)
以下に編集可能なセルを表示するサンプルコードを示す。
◇サンプルコード
package application_fx;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TestCellFactory2 extends Application {
public static void main(String[] args)
{
launch( args );
}
@Override
public void start(Stage primaryStage) throws Exception
{
// シーングラフを作成
VBox root = new VBox( 2.0 );
// 編集可能なセルを作成するファクトリを定義
Callback<ListView<String>,ListCell<String>> cellFactory = p -> new EditableCell();
// リストビューを作成
ListView<String> listView = new ListView<>();
listView.setEditable( true );
listView.setItems( FXCollections.observableArrayList( "その1" , "その2" , "その3" ) );
listView.setCellFactory( cellFactory );
//listView.setCellFactory( TextFieldListCell.forListView() );
root.getChildren().add( listView );
// シーンを作成
Scene scene = new Scene( root , 500 , 200 , Color.web( "9FCC7F" ) );
// ウィンドウ表示
primaryStage.setScene( scene );
primaryStage.show();
}
/**
* 編集可能なセル
* @author tomo
*
*/
class EditableCell extends ListCell<String>
{
private TextField textField;
public EditableCell(){}
/**
* 編集開始時の処理
*/
@Override
public void startEdit()
{
// 元関数を呼び出し
super.startEdit();
// 編集フィールドを作成
textField = new TextField( this.getItem() );
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
// 編集用フィールドからフォーカスが外れた場合に
// 編集内容を確定(commit)するようにリスナーを設定
textField.focusedProperty().addListener(
( ov , old , current ) ->
{ if( !current ){ commitEdit( textField.getText() );} }
);
// 表示を変更
setText( null );
setGraphic( textField );
textField.selectAll();
}
/**
* 編集破棄時の処理
*/
@Override
public void cancelEdit()
{
// 元関数を呼び出し
super.cancelEdit();
// 編集内容の破棄
setText( this.getItem() );
setGraphic( null );
}
/**
* セルの更新時処理
* @param item
* @param empty
*/
@Override
public void updateItem( String item , boolean empty )
{
// 元関数を呼び出し
super.updateItem(item, empty);
// 空の場合
if( empty )
{
setText( null );
setGraphic( null );
return;
}
// 編集中の場合
if( isEditing() )
{
if( textField != null ){ textField.setText( toString() ); }
setText( null );
setGraphic( textField );
return;
}
// その他の場合
setText( this.getItem() );
setGraphic( null );
}
}
}
◇実行結果
◇解説
セル・ファクトリは28行目で設定しており、EditableCellクラスのインスタンスを返すだけの関数である。EditableCellクラスは51行目~131行目で宣言している。EditableCellクラスはListCellクラスを継承し、startEdit(61行目~81行目)・cancelEdit(87行目~95行目)・updateItem(103行目~129行目)の3関数をオーバーライドしている。startEdit関数では編集開始時の処理としてテキストフィールドを表示している。cancelEdit関数では表示を元に戻す処理を、updateItem関数では編集中に表示を変更するように処理している。
ちなみに、今回はListCellを継承したクラスを作成したが、編集可能なセルはJavaで用意されており、TextFieldListCell.forListView関数(35行目)で取得することができる。同様にJavaであらかじめ用意されているCellクラスは以下のとおりである。それぞれに「クラス名.for○○」という静的(static)な関数が存在し、この関数を呼び出すことでsetCellFactory関数に渡すCallBackインスタンスを作成できる。
UIコントロール |
セルのクラス |
内容 |
ComboBox
ListView |
CheckBoxListCell
ChoiceBoxListCell
ComboBoxListCell
TextFieldListCell |
セル内にチェックボックスを表示
編集モードの場合にChoiceBoxを表示
編集モードの場合にComboBoxを表示
編集モードの場合にTextFieldを表示 |
TreeView |
CheckBoxTreeCell
ChoiceBoxTreeCell
ComboBoxTreeCell
TextFieldTreeCell |
セル内にチェックボックスを表示
編集モードの場合にChoiceBoxを表示
編集モードの場合にComboBoxを表示
編集モードの場合にTextFieldを表示 |
TableView |
CheckBoxTableCell
ChoiceBoxTableCell
ComboBoxTableCell
ProgressBarTableCell
TextFieldTableCell |
セル内にチェックボックスを表示
編集モードの場合にChoiceBoxを表示
編集モードの場合にComboBoxを表示
セル内にプログレス・バーを表示
編集モードの場合にTextFieldを表示 |
TreeTableView |
CheckBoxTreeTableCell
ChoiceBoxTreeTableCell
ComboBoxTreeTableCell
ProgressBarTreeTableCell
TextFieldTreeTableCell |
セル内にチェックボックスを表示
編集モードの場合にChoiceBoxを表示
編集モードの場合にComboBoxを表示
セル内にプログレス・バーを表示
編集モードの場合にTextFieldを表示 |
■ 参照