TableView,如何使用数组变量填充数据

TableView, how to use array variables to populate data

我有一个程序,我可以在其中向 table 添加行和列,并且它们充满了数据。用户也可以通过单击来修改单元格。问题是,每当他更改一个单元格的值时,整行都会更改为相同的值。我希望每个单元格都有自己独立的值(也适用于新添加的列)。

public class TableData {
public int digitCell;
public static int numberOfColumns = 0;

public TableData(int digit) {   
    this.digitCell = digit;
}

public int getDigitCell() {
    return digitCell;
}

public void setDigitCell(int digit) {
    this.digitCell = digit;
}

//this method creates and return new column and is used whenever the user clicks add new column
public static TableColumn<TableData, Integer> addNewColumn(TableView<?> table){
    int columnWidth = 10;

    TableColumn<TableData, Integer> newColumn = new TableColumn<>("#" + String.valueOf(numberOfColumns));

    newColumn.setCellFactory(TextFieldTableCell.<TableData, Integer>forTableColumn(new IntegerStringConverter()));
    //Callback<TableColumn<TableData, Integer>, TableCell<TableData,Integer>> cellCallback = (TableColumn<DataModel,Integer> p) -> new NowaKlasa();  

    newColumn.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<TableData,Integer>>() {    
        @Override
        public void handle(CellEditEvent<TableData, Integer> event) {
            ((TableData) event.getTableView().getItems(). get(event.getTablePosition().getRow())).  setDigitCell(event.getNewValue());  
        }
    });

    newColumn.prefWidthProperty().bind(table.widthProperty().divide(100/columnWidth));
    newColumn.setMinWidth(25);
    newColumn.setMaxWidth(50);

    newColumn.setCellValueFactory(new PropertyValueFactory<TableData, Integer>("digitCell"));
    ++numberOfColumns;
    return newColumn;
}

}

主要Class:

public class Main extends Application {

private BorderPane root;
private Button buttAddColumn;
private Button buttDeleteColumn;
private Button buttAddRow;
private Button buttDeleteRow;
private TableView<TableData> tableView;
private HBox hBox;

private ObservableList<TableData> dataList = FXCollections.observableArrayList(/*dodamy tutaj dane kiedy uzytkownik doda nowy rząd*/);

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

@Override
public void init() {
    root = new BorderPane(); 

    //buttony..................
    buttAddColumn = new Button("Dodaj kolumnę");
    buttAddColumn.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            buttAddColumnAction(event);
        }
    });
    buttDeleteColumn = new Button("Usuń kolumnę");
    buttDeleteColumn.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            buttDeleteColumnAction(event);
        }
    });
    buttAddRow = new Button("Dodaj wiersz");
    buttAddRow.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            buttAddRowAction(event);
        }
    });
    buttDeleteRow = new Button("Usuń wiersz");
    buttDeleteRow.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            buttDeleteRowAction(event);
        }
    });
    //koniec buttonow................

    hBox = new HBox();
    tableView = new TableView<TableData>();

    hBox.getChildren().addAll(buttAddColumn, buttAddRow, buttDeleteColumn, buttDeleteRow);
    tableView.setItems(dataList);
    tableView.setPlaceholder(new Label("Click button to add new columns."));
    tableView.setEditable(true);

    root.setCenter(tableView);
    root.setBottom(hBox);
}


private void buttAddRowAction(ActionEvent event) {
    Random rand = new Random();
    dataList.add(new TableData(rand.nextInt(10)));
}
private void buttDeleteRowAction(ActionEvent event) {
    dataList.remove(dataList.size()-1);

}
private void buttAddColumnAction(ActionEvent event) {
    tableView.getColumns().add(TableData.addNewColumn(tableView));
}
private void buttDeleteColumnAction(ActionEvent event) {
    tableView.getColumns().remove(TableData.numberOfColumns -1);
    TableData.numberOfColumns--;
}

}

我认为问题是,如果我想存储每个单元格的值,那么我需要在数据中 class 与行中的单元格一样多的变量。但是我不知道如何重新实现程序来做类似的事情。 ??????

成功了!

在这个程序中,用户可以添加行和列,每个单元格都有自己的变量。当用户添加新列时,程序会为每个数据对象动态创建另一个变量(在数组中)并存储来自该单元格的值。所以改变一个单元格,不会影响任何其他单元格......:)

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. Unique number for each 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){

}
private void buttAddRowAction(ActionEvent event){
    dataList.add(new MyData(numberOfColumns));

}
private void buttDeleteRowAction(ActionEvent event){

}

//*******************************************************************
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)));
    }
}

//*******************************************************************
@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);
}
}