如何更新JAVAFX的表视图中每行的值

时间:2017-01-02 09:54:56

标签: java javafx tableview javafx-2 javafx-8

我想创建具有动态列和行的表视图,所以我想从我的数据源中获取像我在swing setValueAt()中使用的值时,从后台更新每个单元格值。 所以基本上我不想创建模型类,因为我的列没有修复,行也没有修复,我不想重新创建表视图来更新表视图中的一行所以请指导我因为我是javafx的Table视图的新手。如果您不理解我的问题,请发表评论

由于

编辑示例源代码

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;

import java.util.*;

public class DynamicTableView extends Application {

private static final int N_COLS = 5;
private static final int N_ROWS = 1000;

public void start(Stage stage) throws Exception {
    TestDataGenerator dataGenerator = new TestDataGenerator();

    TableView<ObservableList<String>> tableView = new TableView<>();

    // add columns
    List<String> columnNames = dataGenerator.getNext(N_COLS);
    for (int i = 0; i < columnNames.size(); i++) {
        final int finalIdx = i;
        TableColumn<ObservableList<String>, String> column = new TableColumn<>(
                columnNames.get(i)
        );
        column.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue().get(finalIdx)));
        tableView.getColumns().add(column);
    }

    // add data
    for (int i = 0; i < N_ROWS; i++) {
        tableView.getItems().add(
                FXCollections.observableArrayList(
                        dataGenerator.getNext(N_COLS)
                )
        );
    }

    tableView.setPrefHeight(200);

    Scene scene = new Scene(tableView);
    stage.setScene(scene);
    stage.show();
}

public static void main(String[] args) {
    launch(args);
}

private static class TestDataGenerator {

    private static final String[] LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tempus cursus diam ac blandit. Ut ultrices lacus et mattis laoreet. Morbi vehicula tincidunt eros lobortis varius. Nam quis tortor commodo, vehicula ante vitae, sagittis enim. Vivamus mollis placerat leo non pellentesque. Nam blandit, odio quis facilisis posuere, mauris elit tincidunt ante, ut eleifend augue neque dictum diam. Curabitur sed lacus eget dolor laoreet cursus ut cursus elit. Phasellus quis interdum lorem, eget efficitur enim. Curabitur commodo, est ut scelerisque aliquet, urna velit tincidunt massa, tristique varius mi neque et velit. In condimentum quis nisi et ultricies. Nunc posuere felis a velit dictum suscipit ac non nisl. Pellentesque eleifend, purus vel consequat facilisis, sapien lacus rutrum eros, quis finibus lacus magna eget est. Nullam eros nisl, sodales et luctus at, lobortis at sem.".split(" ");

    private int curWord = 0;

    List<String> getNext(int nWords) {
        List<String> words = new ArrayList<>();

        for (int i = 0; i < nWords; i++) {
            if (curWord == Integer.MAX_VALUE) {
                curWord = 0;
            }

            words.add(LOREM[curWord % LOREM.length]);
            curWord++;
        }

        return words;
    }
}
}

1 个答案:

答案 0 :(得分:2)

正如the javadoc所说,持有表模型的属性是项目。你可以这样做:

table.getItems()

并使用它(添加,删除,清除......)。

正如我在你的例子中看到的,你有一个字符串表。要选择每列上显示的内容,您必须使用setValueFactory()。这样每个列都将知道如何呈现每个值。让我们说你有字符串:

"Hi how are you?"

你正试图获得这样的4列:

hi | how | are | you?

你可以在每一列上设置并设置一个cellValueFactory来分割param.getValue()并获取其对应的索引。

编辑:添加了你的changeValueAt():

public class DynamicTableView extends Application {

private static final int N_COLS = 5;
private static final int N_ROWS = 1000;

public void start(Stage stage) throws Exception {
    TestDataGenerator dataGenerator = new TestDataGenerator();

    TableView<ObservableList<String>> tableView = new TableView<>();

    // add columns
    List<String> columnNames = dataGenerator.getNext(N_COLS);
    for (int i = 0; i < N_COLS; i++) {
        final int index = i;
        TableColumn<ObservableList<String>, String> column = new TableColumn<>(columnNames.get(i));
        column.setCellValueFactory(cellData -> new ReadOnlyObjectWrapper<>((cellData.getValue().get(index))));
        tableView.getColumns().add(column);
    }

    // add data
    for (int i = 0; i < N_ROWS; i++) {
        tableView.getItems().add(FXCollections.observableArrayList(dataGenerator.getNext(N_COLS)));
    }

    tableView.setPrefHeight(200);

    Scene scene = new Scene(tableView);
    stage.setScene(scene);
    stage.show();
    changeValueAt(0,0, "thisIsMyNewValue", tableView);

}

private static void changeValueAt(int row, int col, String value, TableView<ObservableList<String>> table){
    ObservableList newData = table.getItems().get(row);
    newData.set(col, value);
    table.getItems().set(row, newData);

}

public static void main(String[] args) {
    launch(args);

}

private static class TestDataGenerator {

    private static final String[] LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tempus cursus diam ac blandit. Ut ultrices lacus et mattis laoreet. Morbi vehicula tincidunt eros lobortis varius. Nam quis tortor commodo, vehicula ante vitae, sagittis enim. Vivamus mollis placerat leo non pellentesque. Nam blandit, odio quis facilisis posuere, mauris elit tincidunt ante, ut eleifend augue neque dictum diam. Curabitur sed lacus eget dolor laoreet cursus ut cursus elit. Phasellus quis interdum lorem, eget efficitur enim. Curabitur commodo, est ut scelerisque aliquet, urna velit tincidunt massa, tristique varius mi neque et velit. In condimentum quis nisi et ultricies. Nunc posuere felis a velit dictum suscipit ac non nisl. Pellentesque eleifend, purus vel consequat facilisis, sapien lacus rutrum eros, quis finibus lacus magna eget est. Nullam eros nisl, sodales et luctus at, lobortis at sem."
            .split(" ");

    private int curWord = 0;

    List<String> getNext(int nWords) {
        List<String> words = new ArrayList<>();

        for (int i = 0; i < nWords; i++) {
            if (curWord == Integer.MAX_VALUE) {
                curWord = 0;
            }

            words.add(LOREM[curWord % LOREM.length]);
            curWord++;
        }

        return words;
    }
}

}

重要的是:

private static void changeValueAt(int row, int col, String value,   TableView<ObservableList<String>> table){
    ObservableList newData = table.getItems().get(row);
    newData.set(col, value);
    table.getItems().set(row, newData);

}

每次属性更改时都会触发渲染器。我只是访问要更改的行中的元素,然后我可以访问列中的元素。通过更改它,更改会被注意到呈现新值的列。

<强>说明

TableView中的泛型类表示TableView持有的ObservableList中的泛型类的类(在items属性中)。此类型与行的类型一致,因此通过执行:

table.getItems().get(0)

您正在检索包含第一行数据的对象,在您的情况下是ObservableList。这就是你的table.getItems()返回

的原因
ObservableList<ObservableList<String>>

(您提供的泛型类型的ObservableList)。

在渲染每一列时,您必须提供一个CellValueFactory,指示TableView泛型类型和列数据类型,然后实现如何从您拥有的信息中获取单元格值。

所有这些都与属性一起工作,就像普通数据类型一样,但更改时会触发事件。这就是我的方法有效的原因,一旦你修改了一个属性,这个属性就会触发改变的事件,并且表格会重新呈现(简短说明)。这里的事情是,这种变化不会传播,所以通过更改列,保存行的列表,每个列保持列不会得到通知。这就是为什么我在修改它之后再次设置同一行的原因。

请理解您的示例非常罕见,因为通常表中包含普通的POJO,并且您与之交互的唯一ObservableList是items属性。