JavaFX - TableView : Simple CRUD

TableViewを利用して、基本的なデータの表示・編集・追加・削除を行なってみたいと思います。

TableViewへのデータの表示は、itemsPropertyに表示したいモデルのObservableListを設定し、データの追加・削除についてはそのObservableListにモデルを追加・削除することによって行います。

では、実際に以下のようなものを作成してみたいと思います。

Name, Gender, Email, Ageを持つUserを表示しています。[+]ボタンで新規にUserを追加し、[-]ボタンで選択されているUserを削除します。

まずは、表示するUserのモデルを以下のように定義します。

public interface UserModel {     StringProperty nameProperty();     ObjectProperty genderProperty();     StringProperty emailProperty();     IntegerProperty ageProperty(); } 

GenderModelは以下のようになります。

public enum GenderModel {     MALE,     FEMALE; } 

次に、このUserModelを表示するViewに対するモデルを以下のように定義します。

public interface UserListModel {     ObjectProperty> usersProperty();     ObjectProperty> userSelectionModelProperty();      void loadUsers();     void addNewUser();     void removeSelectedUser(); }  

UserModelの読み込み・追加・削除を行うメソッドを定義しています。また、TableViewのselectionModelプロパティからTableViewで選択されている状態を取得したいので、それをバインドして取得できるようにuserSelectionModelプロパティを定義しています。

UserModelを表示するViewを以下のように定義します。

                                                                                               

UserModelを表示するTableViewと、UserModelの追加・削除のためのボタンを定義しています。

このViewのコントローラを以下のようにします。

public class UserListView extends HBox {     public ObjectProperty modelProperty() { return model; }     private final ObjectProperty model = new SimpleObjectProperty(this, "model") {         private UserListModel currentModel;          @Override         protected void invalidated() {             UserListView.this.unbind(currentModel);             currentModel = get();             UserListView.this.bind(currentModel);         }     };     public final UserListModel getModel() { return model.get(); }     public final void setModel(UserListModel model) { this.model.set(model); }      @FXML     private TableView userTableView;     @FXML     private TableColumn nameTableColumn;     @FXML     private TableColumn genderTableColumn;     @FXML     private TableColumn emailTableColumn;     @FXML     private TableColumn ageTableColumn;     @FXML     private Button addUserButton;     @FXML     private Button removeUserButton;      public UserListView() {         getStyleClass().add("user-list-view");         initializeComponent();     }      protected void initializeComponent() {         FXController.of(this).fromDefaultLocation().load();     }      protected void bind(UserListModel model) {         if (model == null) { return; }          userTableView.itemsProperty().bindBidirectional(model.usersProperty());         model.userSelectionModelProperty().bind(userTableView.selectionModelProperty());     }      protected void unbind(UserListModel model) {         if (model == null) { return; }          userTableView.itemsProperty().unbindBidirectional(model.usersProperty());         model.userSelectionModelProperty().unbind();     }      protected void addUser() {         if (getModel() == null) { return; }          getModel().addNewUser();         userTableView.requestFocus();     }      protected void removeUser() {         if (getModel() == null) { return; }          getModel().removeSelectedUser();         userTableView.requestFocus();     }      @FXML     protected void initialize() {         nameTableColumn.setCellValueFactory(new PropertyValueFactory("name"));         nameTableColumn.setCellFactory(TextFieldTableCell.forTableColumn());          genderTableColumn.setCellValueFactory(new PropertyValueFactory("gender"));         genderTableColumn.setCellFactory(ChoiceBoxTableCell.forTableColumn(GenderModel.values()));          emailTableColumn.setCellValueFactory(new PropertyValueFactory("email"));         emailTableColumn.setCellFactory(TextFieldTableCell.forTableColumn());          ageTableColumn.setCellValueFactory(new PropertyValueFactory("age"));         ageTableColumn.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter()));          addUserButton.setOnAction(new EventHandler() {             @Override             public void handle(ActionEvent event) {                 addUser();             }         });          removeUserButton.setOnAction(new EventHandler() {             @Override             public void handle(ActionEvent event) {                 removeUser();             }         });     } } 

UserListModelを設定したときに、UserListModelで定義されているプロパティとTableViewのプロパティをバインドしています。[+]ボタンが押下されたときに、UserListModelのaddNewUserメソッドを呼び出してUserModelを追加し、[-]ボタンが押下されたときに、UserListModelのremoveSelectedUserメソッドを呼び出して選択されているUserModelを削除するようにしています。

以上で準備ができましたので、このUserListViewを表示していきます。

まずは、モデルを以下のように定義します。

public interface TableViewSimpleCRUDDemoModel {     ObjectProperty userListModelProperty();      void initialize(); } 

次に、Viewを以下のように定義します。

                                         

このViewのコントローラを以下のようにします。

public class TableViewSimpleCRUDDemoSceneController {     public ObjectProperty modelProperty() { return model; }     private final ObjectProperty model = new SimpleObjectProperty(this, "model") {         private TableViewSimpleCRUDDemoModel currentModel;         @Override         protected void invalidated() {             TableViewSimpleCRUDDemoSceneController.this.unbind(currentModel);             currentModel = get();             TableViewSimpleCRUDDemoSceneController.this.bind(currentModel);         }     };     public final TableViewSimpleCRUDDemoModel getModel() { return model.get(); }     public final void setModel(TableViewSimpleCRUDDemoModel model) { this.model.set(model); }      @FXML     private Scene scene;     @FXML     private UserListView userListView;      public void performOn(Stage stage) {         stage.setScene(scene);         stage.setTitle("Simple CRUD for Table View Demo");         stage.sizeToScene();         stage.centerOnScreen();         stage.show();     }      public TableViewSimpleCRUDDemoSceneController with(TableViewSimpleCRUDDemoModel model) {         setModel(model);         if (model != null) { model.initialize(); }          return this;     }      protected void bind(TableViewSimpleCRUDDemoModel model) {         if (model == null) { return; }          userListView.modelProperty().bindBidirectional(model.userListModelProperty());     }      protected void unbind(TableViewSimpleCRUDDemoModel model) {         if (model == null) { return; }          userListView.modelProperty().unbindBidirectional(model.userListModelProperty());     } } 

あとは、各モデルのデフォルトの実装を行っておきます。

まずは、UserModelのデフォルトの実装を以下のようにします。

public class DefaultUserModel implements UserModel {     @Override     public StringProperty nameProperty() { return name; }     private final StringProperty name = new SimpleStringProperty(this, "name");     public final String getName() { return name.get(); }     public final void setName(String name) { this.name.set(name); }      @Override     public ObjectProperty genderProperty() { return gender; }     private final ObjectProperty gender = new SimpleObjectProperty<>(this, "gender");     public final GenderModel getGender() { return gender.get(); }     public final void setGender(GenderModel gender) { this.gender.set(gender); }      @Override     public StringProperty emailProperty() { return email; }     private final StringProperty email = new SimpleStringProperty(this, "email");     public final String getEmail() { return email.get(); }     public final void setEmail(String email) { this.email.set(email); }      @Override     public IntegerProperty ageProperty() { return ageProperty; }     private final IntegerProperty ageProperty = new SimpleIntegerProperty(this, "ageProperty");     public final int getAge() { return ageProperty.get(); }     public final void setAge(int ageProperty) { this.ageProperty.set(ageProperty); }      protected DefaultUserModel(String name, GenderModel gender, String email, int age) {         setName(name);         setGender(gender);         setEmail(email);         setAge(age);     }      public static DefaultUserModel asMale(String name, String email, int age) {         return new DefaultUserModel(name, GenderModel.MALE, email, age);     }      public static DefaultUserModel asFemale(String name, String email, int age) {         return new DefaultUserModel(name, GenderModel.FEMALE, email, age);     }      public static DefaultUserModel newUser() {         return new DefaultUserModel("Unknown", GenderModel.MALE, "", 20);     } } 

次に、UserListModelのデフォルトの実装を以下のようにします。

public class DefaultUserListModel implements UserListModel {     @Override     public ObjectProperty> usersProperty() { return users; }     private final ObjectProperty> users = new SimpleObjectProperty<>(this, "users");     public final ObservableList getUsers() { return users.get(); }     public final void setUsers(ObservableList users) { this.users.set(users); }      @Override     public ObjectProperty> userSelectionModelProperty() { return userSelectionModel; }     private final ObjectProperty> userSelectionModel = new SimpleObjectProperty<>(this, "userSelectionModel");     public final TableView.TableViewSelectionModel getUserSelectionModel() { return userSelectionModel.get(); }     public final void setUserSelectionModel(TableView.TableViewSelectionModel userSelectionModel) { this.userSelectionModel.set(userSelectionModel); }      @Override     public void loadUsers() {         setUsers(             FXCollections.observableArrayList(                 DefaultUserModel.asMale("User 1", "[email protected]", 25),                 DefaultUserModel.asFemale("User 2", "[email protected]", 28),                 DefaultUserModel.asFemale("User 3", "[email protected]", 24),                 DefaultUserModel.asMale("User 4", "[email protected]", 21),                 DefaultUserModel.asFemale("User 5", "[email protected]", 26)             )         );     }      @Override     public void addNewUser() {         if (getUsers() == null) { setUsers(FXCollections.observableArrayList()); }          getUsers().add(DefaultUserModel.newUser());         if (getUserSelectionModel() != null) { getUserSelectionModel().selectLast(); }     }      @Override     public void removeSelectedUser() {         if (getUsers() == null) { return; }         if (getUserSelectionModel() == null) { return; }          getUsers().remove(getUserSelectionModel().getSelectedItem());     } } 

loadUsersでは、サンプルデータとして5件のUserModelを設定しています。

最後に、TableViewSimpleCRUDDemoModelのデフォルトの実装を以下のようにします。

public class DefaultTableViewSimpleCRUDDemoModel implements TableViewSimpleCRUDDemoModel {     @Override     public ObjectProperty userListModelProperty() { return userListModel; }     private final ObjectProperty userListModel = new SimpleObjectProperty<>(this, "userListModel");     public final UserListModel getUserListModel() { return userListModel.get(); }     public final void setUserListModel(UserListModel userListModel) { this.userListModel.set(userListModel); }      @Override     public void initialize() {         setUserListModel(new DefaultUserListModel());         getUserListModel().loadUsers();     } } 

以上ですべての実装が完了しましたので、Applicationクラスを以下のようにして実行します。

public class TableViewSimpleCRUDDemo extends Application {     @Override     public void start(Stage primaryStage) throws Exception {         FXController.of(new TableViewSimpleCRUDDemoSceneController())             .fromDefaultLocation()             .load()             .with(new DefaultTableViewSimpleCRUDDemoModel())             .performOn(primaryStage);     }      public static void main(String... args) {         launch(args);     } } 

TableViewを利用して、基本的なデータの表示・編集・追加・削除を行なってみました。データの操作はモデル側で行い、Viewへの表示については、モデルのプロパティをViewのプロパティにバインドすることで行うことになります。

Big thanks to this blog author

Latest blog

Web Analytics