【问题标题】:TableView, custom cell editing behaviourTableView,自定义单元格编辑行为
【发布时间】:2015-02-04 21:55:14
【问题描述】:

我有这个适用于 TableView 的应用程序。它添加/删除新的行或列并为每个单元格存储数据。

public class MyTable extends Application {
private BorderPane root;
private HBox hBox;
private TableView<MyData> tableView;    
private Button buttAddColumn, buttDeleteColumn;
private Button buttAddRow, buttDeleteRow;
private int numberOfColumns = 0;
private ObservableList<MyData> dataList = FXCollections.observableArrayList();
@Override
public void init() throws Exception {
    root = new BorderPane();
    hBox = new HBox();
    buttAddColumn = new Button("Add columns");
    buttDeleteColumn = new Button("Delete columns");
    buttAddRow = new Button("Add rows");
    buttDeleteRow = new Button("Delete rows");
    tableView = new TableView<>();

    tableView.setEditable(true);
    tableView.setItems(dataList);
    hBox.getChildren().addAll(buttAddColumn,buttDeleteColumn,buttAddRow,buttDeleteRow);

    root.setTop(hBox);
    root.setCenter(tableView);


    //----------------------------------------------------------------
    buttAddColumn.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            buttAddColumnAction(event);
        }
    });
    buttDeleteColumn.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            buttDeleteColumnAction(event);
        }
    });
    buttAddRow.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            buttAddRowAction(event);
        }
    });
    buttDeleteRow.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            buttDeleteRowAction(event);
        }
    });
}

private void buttAddColumnAction(ActionEvent event){        
    int i = numberOfColumns;// thats the key for lambda expression. Unicate number for column to access its variable;

    if(dataList.size() > 0)//resizing each data object with new variable
        for(MyData x: dataList)
            x.addNew(i);
    TableColumn<MyData, Integer> newColumn = new TableColumn<>("#" + String.valueOf(++numberOfColumns));    
    newColumn.setCellValueFactory(cellData -> cellData.getValue().getCellValue(i).asObject());
    newColumn.setCellFactory(TextFieldTableCell.<MyData, Integer>forTableColumn(new IntegerStringConverter()));

    tableView.getColumns().add(newColumn);
}
private void buttDeleteColumnAction(ActionEvent event){
    if(numberOfColumns > 0){
        tableView.getColumns().remove(numberOfColumns-1);
        --numberOfColumns;

        if(dataList.size() > 0)
            for(MyData x: dataList) //deleting unnecesary variable
                x.deleteLast();
    }
}
private void buttAddRowAction(ActionEvent event){
    dataList.add(new MyData(numberOfColumns)); 
}
private void buttDeleteRowAction(ActionEvent event){
    if(dataList.size() > 0){//resizing each data object with new variable
        dataList.remove(dataList.size()-1);
    }
}

//*******************************************************************
public class MyData{ //dont forget about public because you wont get acces to properties
    private ObservableList<SimpleIntegerProperty> cellValue = FXCollections.observableArrayList();

    public MyData(int howManyColumns) {
        for(int i=0; i<howManyColumns; ++i)
           this.cellValue.add(new SimpleIntegerProperty(new Random().nextInt(10)));
    }

    public SimpleIntegerProperty getCellValue(int whichOne) {
        return cellValue.get(whichOne);
    }

    public void setCellValue(int cellValue, int whichOne) {
        this.cellValue.set(whichOne, new SimpleIntegerProperty(cellValue));
    }

    public void addNew(int numberOfNewElement){ //ads another variable for another column
        cellValue.add(new SimpleIntegerProperty(new Random().nextInt(10)));
    }
    public void deleteLast(){ //deletes last variable when column is deleted
        cellValue.remove(cellValue.size()-1);
    }
}

//*******************************************************************
@Override
public void start(Stage primaryStage) throws Exception {
    try {
        Scene scene = new Scene(root,400,400);
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}
public static void main(String[] args) {
    launch(args);
}

}

我怎样才能改变它,所以当用户双击单元格时,程序会等到他按下 0-9 的单个数字,然后自动接受它并打开下一个单元格来放置另一个数字(所以他不需要手动打开/关闭它们)?

我目前不知道如何做到这一点。甚至如何使空单元格等待数据(也许数据类应该由char 变量而不是Integer 组成,所以我可以将值"" 放入单元格???)

【问题讨论】:

    标签: tableview javafx-8


    【解决方案1】:

    6 小时左右,我成功了……

    我必须在每一列中添加类似的内容,这是处理单元格编辑事件的类。

    Callback<TableColumn<MyData, Integer>, TableCell<MyData, Integer>> cellFactoryInt = (TableColumn<MyData, Integer> p) -> new EditingCellNumbers(tableView);
    newColumn.setCellFactory(cellFactoryInt);
    

    这里实现这个类:

    package application;
    
    import application.MyTable.MyData;
    import javafx.beans.value.ObservableValue;
    import javafx.event.Event;
    import javafx.event.EventHandler;
    import javafx.scene.control.TableCell;
    import javafx.scene.control.TableView;
    import javafx.scene.control.TextField;
    
    //Klasa ta pozwala na definiowania zachowania komórek, które edytuje użytkownik
    public class EditingCellNumbers extends TableCell<MyData, Integer>{ 
        private TextField textField;
        private TableView<MyData> parentTableView;
        public static int numberOfColumns;
    
        public EditingCellNumbers(TableView<MyData> parent) {
            this.parentTableView = parent;
            numberOfColumns = parent.getColumns().size();
        }
    
        @Override
        public void startEdit(){
            if (!isEmpty()) {
                super.startEdit();
                createTextField();
                setText(null);
                setGraphic(textField);
                textField.selectAll();
                textField.requestFocus();
            }
        }
    
        @Override
        public void cancelEdit() {
            super.cancelEdit();
    
            setText(String.valueOf(getItem()));
            setGraphic(null);
        }
    
        @Override
        public void updateItem(Integer 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(
                (ObservableValue<? extends Boolean> arg0, 
                Boolean arg1, Boolean arg2) -> {
                    if (!arg2) {
                        commitEdit(Integer.valueOf(textField.getText()));
                    }
            });
            textField.setOnKeyReleased(new EventHandler<Event>() {
                @Override
                public void handle(Event event) {
                    try{
                        int i = Integer.valueOf(textField.getText());
                        //digit given...
                        if( (i>=0) && (i<10) ){//making sure cell is filled with just one digit
                           commitEdit(Integer.valueOf(textField.getText()));
                           int selectedColumn = parentTableView.getSelectionModel().getSelectedCells().get(0).getColumn(); // gets the number of selected column
                           int selectedRow = parentTableView.getSelectionModel().getSelectedCells().get(0).getRow();
                           if(selectedColumn < numberOfColumns-1){
                               parentTableView.getSelectionModel().selectNext();
                               parentTableView.edit(selectedRow, parentTableView.getColumns().get(selectedColumn+1));
                           }else{
                               parentTableView.getSelectionModel().select(selectedRow+1, parentTableView.getColumns().get(0));
                               parentTableView.edit(selectedRow+1, parentTableView.getColumns().get(0));
    
                           }
    
                        }else
                           textField.clear();
                    }catch(NumberFormatException e){
                        textField.clear();
                    }
                }
            });
        }
    
        private String getString() {
            return getItem() == null ? "" : getItem().toString();
        }
    }
    

    这里是一点点编辑的应用程序类:

    public class MyTable extends Application {
    private BorderPane root;
    private HBox hBox;
    private TableView<MyData> tableView;    
    private Button buttAddColumn, buttDeleteColumn;
    private Button buttAddRow, buttDeleteRow;
    private int numberOfColumns = 0;
    private ObservableList<MyData> dataList = FXCollections.observableArrayList();
    
        @Override
        public void init() throws Exception {
            root = new BorderPane();
            buttAddColumn = new Button("Add columns");
            buttDeleteColumn = new Button("Delete columns");
            buttAddRow = new Button("Add rows");
            buttDeleteRow = new Button("Delete rows");
            tableView = new TableView<>();
            hBox = new HBox();
            hBox.getChildren().addAll(buttAddColumn,buttDeleteColumn,buttAddRow,buttDeleteRow);
    
            tableView.setEditable(true);
            tableView.getSelectionModel().setCellSelectionEnabled(true);
            tableView.setItems(dataList);
    
            root.setTop(hBox);
            root.setCenter(tableView);
    
            //----------------------------------------------------------------
            buttAddColumn.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    buttAddColumnAction(event);
                }
            });
            buttDeleteColumn.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    buttDeleteColumnAction(event);
                }
            });
            buttAddRow.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    buttAddRowAction(event);
                }
            });
            buttDeleteRow.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    buttDeleteRowAction(event);
                }
            });
    
        }
    
        private void buttAddColumnAction(ActionEvent event){        
            int i = numberOfColumns;// thats the key for lambda expression. Unicate number for column to access its variable;
    
            if(dataList.size() > 0)//resizing each data object with new variable
                for(MyData x: dataList)
                    x.addNew(i);
    
            TableColumn<MyData, Integer> newColumn = new TableColumn<>("#" + String.valueOf(++numberOfColumns));
    
            newColumn.setCellValueFactory(cellData -> cellData.getValue().getCellValue(i).asObject());
            newColumn.setCellFactory(TextFieldTableCell.<MyData, Integer>forTableColumn(new IntegerStringConverter()));
    
            Callback<TableColumn<MyData, Integer>, TableCell<MyData, Integer>> cellFactoryInt = (TableColumn<MyData, Integer> p) -> new EditingCellNumbers(tableView);
            newColumn.setCellFactory(cellFactoryInt);
            tableView.getColumns().add(newColumn);
        }
        private void buttDeleteColumnAction(ActionEvent event){
            if(numberOfColumns > 0){
                tableView.getColumns().remove(numberOfColumns-1);
                --numberOfColumns;
                --EditingCellNumbers.numberOfColumns;
                if(dataList.size() > 0)
                    for(MyData x: dataList) //deleting unnecesary variable
                        x.deleteLast();
            }
        }
        private void buttAddRowAction(ActionEvent event){
            dataList.add(new MyData(numberOfColumns)); 
        }
        private void buttDeleteRowAction(ActionEvent event){
            if(dataList.size() > 0){//resizing each data object with new variable
                dataList.remove(dataList.size()-1);
            }
        }
        //*******************************************************************
        public class MyData{ //dont forget about public because you wont get acces to properties
            private ObservableList<SimpleIntegerProperty> cellValue = FXCollections.observableArrayList();
    
            public MyData(int howManyColumns) {
                for(int i=0; i<howManyColumns; ++i)
                   this.cellValue.add(new SimpleIntegerProperty(new Random().nextInt(10)));
            }
    
            public SimpleIntegerProperty getCellValue(int whichOne) {
                return cellValue.get(whichOne);
            }
    
            public void setCellValue(int cellValue, int whichOne) {
                this.cellValue.set(whichOne, new SimpleIntegerProperty(cellValue));
            }
    
            public void addNew(int numberOfNewElement){ //ads another variable for another column
                cellValue.add(new SimpleIntegerProperty(new Random().nextInt(10)));
            }
            public void deleteLast(){ //deletes last variable when column is deleted
                cellValue.remove(cellValue.size()-1);
            }
        }
    
        //*******************************************************************
        @Override
        public void start(Stage primaryStage) throws Exception {
            try {
                Scene scene = new Scene(root,400,400);
                primaryStage.setScene(scene);
                primaryStage.show();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args) {
            launch(args);
        }
    
    }
    

    很多代码,但也许将来有人会使用它:P

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-22
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      相关资源
      最近更新 更多