JavaFX 2 TableView에서 데이터의 Null 값을 처리하는 데 심각한 문제가 있습니다. 실제로 많은 문제가 있습니다. 아래에 표시된 문제에 대한 간단한 데모를 작성했습니다.셀의 null 값 처리
본질적으로 문제는 일부 데이터가 null 일 수 있으며 빈 문자열과 같은 값으로 null을 강요하는 것은 유효하지 않으며 null이어야합니다. 실제 코드에서 저는 null 값을 가지고 있습니다. 예제를 단순하게 유지하려면 아래에 null 문자열을 보여 줬습니다.
테이블의 행 1과 테이블 2에는 널값이 있습니다. 두 개의 열은 서로 다르며 첫 번째 행은 편집 가능한 셀의 두 번째 구현 인 TextFieldTableCell의 동작을 보여줍니다. 둘 다 같은 잘못된 동작을 보여줍니다.
현재의 행동이 이것이다 :
- 눌러 편집을 커밋 입력 셀에 값을 입력 편집 모드
- 를 입력 할 셀을 클릭
- 아무것도
4 단계에서 열의 onEditCommit 처리기가 호출 될 것으로 예상되지만 그렇지 않습니다. (가) 때문에 것은, commitEdit의 첫 번째 줄의 발생하지 커밋 javax.scene.control.TableCell의 소스를 살펴 갖는 것입니다 :
if (! isEditing()) return;
세포이기 때문에 널 편집 속성이 설정 결코 극복 보인다 나는 아직까지 모든 코드를 추적하지 못했지만 왜 그것이 사실로 바뀌지 않는지를 알기는하지만 인정합니다.
언제나 도움을 주셔서 감사합니다.
예
기본 응용 프로그램
package example;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.stage.Stage;
import javafx.util.Callback;
public class NullCellEditingExample extends Application {
private TableView table = new TableView();
private final ObservableList<Person> data =
FXCollections.observableArrayList(new Person(null, "Smith"), new Person("Isabella", null),
new Person("Ethan", "Williams"), new Person("Emma", "Jones"), new Person("Michael", "Brown"));
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
TableColumn firstNameCol = createSimpleFirstNameColumn();
TableColumn lastNameCol = createLastNameColumn();
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol);
table.setEditable(true);
((Group) scene.getRoot()).getChildren().addAll(table);
stage.setScene(scene);
stage.show();
}
private TableColumn createSimpleFirstNameColumn() {
TableColumn firstNameCol = new TableColumn("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn());
firstNameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() {
@Override
public void handle(TableColumn.CellEditEvent<Person, String> t) {
((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setFirstName(t.getNewValue());
}
});
return firstNameCol;
}
private TableColumn createLastNameColumn() {
Callback<TableColumn, TableCell> editableFactory = new Callback<TableColumn, TableCell>() {
@Override
public TableCell call(TableColumn p) {
return new EditingCell();
}
};
TableColumn lastNameCol = new TableColumn("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
lastNameCol.setCellFactory(editableFactory);
lastNameCol.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Person, String>>() {
@Override
public void handle(TableColumn.CellEditEvent<Person, String> t) {
t.getRowValue().setLastName(t.getNewValue());
}
});
return lastNameCol;
}
}
편집 셀
package example;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
public class EditingCell extends TableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
@Override
public void startEdit() {
super.startEdit();
if(textField == null) {
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()); }
}
});
textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
String value = textField.getText();
if (value != null) { commitEdit(value); } else { commitEdit(null); }
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
사람
package example;
import javafx.beans.property.SimpleStringProperty;
public class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
public Person(String firstName, String lastName) {
this.firstName = new SimpleStringProperty(firstName);
this.lastName = new SimpleStringProperty(lastName);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public SimpleStringProperty firstNameProperty() {
return firstName;
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public SimpleStringProperty lastNameProperty() {
return lastName;
}
}