How to make a table column with Integer datatype editable without changing it to String

后端 未结 2 1801
傲寒
傲寒 2020-12-18 04:22

I have a table column with datatype Integer. i want to make this column editable without changing the datatype to String anywhere. I used textfieldtablecell but it commits v

相关标签:
2条回答
  • 2020-12-18 04:52

    You can create table cell with StringConverter, that will convert your object to cell presentation. You can realize own StringConverter for your class

    cell.setCellFactory(TextFieldTableCell.forTableColumn(new StringConverter<AnyClass>() {
    
            @Override
            public String toString(AnyClass object) {
                return null;
            }
    
            @Override
            public AnyClass fromString(String string) {
                return null;
            }
        }));
    

    Also JavaFX contains some default converters. E.g. IntegerStringConverter for your case,

    TextFieldTableCell.forTableColumn(new IntegerStringConverter())
    
    0 讨论(0)
  • 2020-12-18 04:58

    Just use a cell factory that creates a text field in the cell when editing. To commit the edit, just parse the text from the text field.

    Example:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.regex.Pattern;
    
    import javafx.application.Application;
    import javafx.beans.property.IntegerProperty;
    import javafx.beans.property.SimpleIntegerProperty;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.TableCell;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.HBox;
    import javafx.stage.Stage;
    
    public class EditableTableColumnWithInteger extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            TableView<Item> table = new TableView<>();
            table.setEditable(true);
            table.getItems().addAll(createData());
    
            TableColumn<Item, String> nameCol = new TableColumn<>("Name");
            nameCol.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
    
            TableColumn<Item, Number> valueCol = new TableColumn<>("Value");
            valueCol.setCellValueFactory(cellData -> cellData.getValue().valueProperty());
    
            valueCol.setCellFactory(col -> new IntegerEditingCell());
    
            table.getColumns().add(nameCol);
            table.getColumns().add(valueCol);
    
            Button dataDumpButton = new Button("Dump data");
            dataDumpButton.setOnAction( e -> 
                table.getItems().stream().map(item -> item.getName()+":"+item.getValue()).forEach(System.out::println));
            HBox controls = new HBox(5, dataDumpButton);
            controls.setPadding(new Insets(10));
            controls.setAlignment(Pos.CENTER);
    
            primaryStage.setScene(new Scene(new BorderPane(table, null, null, controls, null), 600, 400));
            primaryStage.show();
        }
    
        public class IntegerEditingCell extends TableCell<Item, Number> {
    
            private final TextField textField = new TextField();
            private final Pattern intPattern = Pattern.compile("-?\\d+");
    
            public IntegerEditingCell() {
                textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
                    if (! isNowFocused) {
                        processEdit();
                    }
                });
                textField.setOnAction(event -> processEdit());
            }
    
            private void processEdit() {
                String text = textField.getText();
                if (intPattern.matcher(text).matches()) {
                    commitEdit(Integer.parseInt(text));
                } else {
                    cancelEdit();
                }
            }
    
            @Override
            public void updateItem(Number value, boolean empty) {
                super.updateItem(value, empty);
                if (empty) {
                    setText(null);
                    setGraphic(null);
                } else if (isEditing()) {
                    setText(null);
                    textField.setText(value.toString());
                    setGraphic(textField);
                } else {
                    setText(value.toString());
                    setGraphic(null);
                }
            }
    
            @Override
            public void startEdit() {
                super.startEdit();
                Number value = getItem();
                if (value != null) {
                    textField.setText(value.toString());
                    setGraphic(textField);
                    setText(null);
                }
            }
    
            @Override
            public void cancelEdit() {
                super.cancelEdit();
                setText(getItem().toString());
                setGraphic(null);
            }
    
            // This seems necessary to persist the edit on loss of focus; not sure why:
            @Override
            public void commitEdit(Number value) {
                super.commitEdit(value);
                ((Item)this.getTableRow().getItem()).setValue(value.intValue());
            }
        }
    
        private List<Item> createData() {
            Random rng = new Random();
            List<Item> items = new ArrayList<>();
            for (int i=1; i<=20; i++) {
                items.add(new Item("Item "+i, rng.nextInt(20)));
            }
            return items ;
        }
    
        public static class Item {
            private final StringProperty name = new SimpleStringProperty();
            private final IntegerProperty value = new SimpleIntegerProperty();
            public Item(String name, int value) {
                this.setName(name);
                this.setValue(value);
            }
            public final StringProperty nameProperty() {
                return this.name;
            }
            public final java.lang.String getName() {
                return this.nameProperty().get();
            }
            public final void setName(final java.lang.String name) {
                this.nameProperty().set(name);
            }
            public final IntegerProperty valueProperty() {
                return this.value;
            }
            public final int getValue() {
                return this.valueProperty().get();
            }
            public final void setValue(final int value) {
                this.valueProperty().set(value);
            }
    
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    0 讨论(0)
提交回复
热议问题