【问题标题】:javafx tableview data from List来自 List 的 javafx tableview 数据
【发布时间】:2018-02-20 14:37:21
【问题描述】:

JavaFX 中的 TableView 有问题。

从定义了所有字段的现有类创建表很容易。

但我想知道是否可以从列表中制作表格并添加数据?

我做了类似的东西,但它有点行不通。

    @FXML
    private TableView<List<String>> testTable;

    ....


    List<String> list = new ArrayList<>();
    list.add("1hello");
    list.add("1hello2");

    List<String> list2 = new ArrayList<>();
    list2.add("2hello");
    list2.add("2hello2");

    ObservableList<List<String>> lists = FXCollections.observableArrayList();
    lists.add(list);
    lists.add(list2);

    TableColumn<List<String>, String> coll = new TableColumn<>("one");
    coll.setCellValueFactory(new PropertyValueFactory<List<String>,String>(""));
    TableColumn<List<String>, String> coll2 = new TableColumn<>("two");
    coll2.setCellValueFactory(new PropertyValueFactory<List<String>,String>(""));

    testTable.getColumns().add(coll);
    testTable.getColumns().add(coll2);

    lists.forEach(li -> {
        System.out.println("list: " +  li);
        testTable.getItems().add(li);

    }); 

它没有插入任何数据。这样的事情可能吗?

【问题讨论】:

标签: arraylist javafx tableview


【解决方案1】:

您可以通过将List 中的String 替换为StringProperty 来做到这一点:

@FXML
private TableView<List<StringProperty>> testTable;

然后:

TableColumn<List<StringProperty>, String> coll = new TableColumn<>("one");

添加 cellValueFactories:

col1.setCellValueFactory(data -> data.getValue().get(0));
col2.setCellValueFactory(data -> data.getValue().get(1));
.
.

等等。

这意味着列表的第一个元素将用于col1,列表的第二个元素将用于col2

然后你可以像这样填充列表:

ObservableList<List<StringProperty>> data = FXCollections.observableArrayList();
List<StringProperty> firstRow = new ArrayList<>();
firstRow.add(0, new SimpleStringProperty("Andrew"));
firstRow.add(1, new SimpleStringProperty("Smith"));
.
.
.
data.add(firstRow);
.
.
.
and so on...
table.setItems(data);

这种方式是可行的,但我会说这是一种非常糟糕的做法

【讨论】:

  • 您也可以使用Strings 执行此操作;只需使用cellData -&gt; new SimpleStringProperty(cellData.getValue().get(0)) 作为单元格值工厂。如果你是,例如创建一个表格来显示解析制表符分隔或 csv 文件等的结果,这是您唯一真正的选择。
  • 但这不会在每次调用值时都创建SimpleStringProperty的新实例?
  • 是的。例如PropertyValueFactory 如果你有一个“传统的”Java bean(没有 JavaFX 属性)也会如此。它适用于数据不变的静态表。
  • 感谢 Sunflame 的回答。我只是好奇有没有可能。 James_D 感谢您的评论和回答。
  • 这可能是一种不好的做法,但有时我们别无选择。例如,我正在从文件中读取数据,并且数据模型在文件之间发生变化。我认为这里的列表可能是我可以选择的最佳实践。
【解决方案2】:

作为我工作的一小部分,我需要一个 TableView,其中包含来自列表的动态填充数据。我在 StackOverflow 和 Oracle 教程中查看了其他一些示例。但没有什么能满足我的需要。

为了满足我的需要,我将不同的解决方案放在一起。请参阅下面的工作示例。

import java.util.ArrayList;
import javafx.util.Callback;
import javafx.util.StringConverter;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.application.Application;

/**
 *
 * @author Rob
 */
public class TableViewSample extends Application {

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

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(400);
        stage.setHeight(500);

        final Label label = new Label("Student IDs");
        label.setFont(new Font("Arial", 20));

        TableView tableView = new TableView<>();
        tableView.setEditable(true);
        tableView.getSelectionModel().setCellSelectionEnabled(true);

        ObservableList<TableColumn> tableViewColumns = generateTableViewColumns();
        tableView.getColumns().setAll(tableViewColumns);

        ObservableList<TableColumn> tcs = tableView.getColumns();
        for (int i = 0; i < tcs.size(); i++) {
            TableColumn tc = tcs.get(i);

            if (i == 0) {
                Callback<TableColumn.CellDataFeatures<ArrayList, Color>, ObservableValue<Color>> cellValueFactory = buildCallbackColor(i);
                tc.setCellValueFactory(cellValueFactory);
            } else {
                Callback<TableColumn.CellDataFeatures<ArrayList, String>, ObservableValue<String>> cellValueFactory = buildCallbackString(i);
                tc.setCellValueFactory(cellValueFactory);
            }

        }

        ObservableList<ArrayList> tableViewRows = generateTableViewRows();
        tableView.getItems().setAll(tableViewRows);

        for (int i = 0; i < tcs.size(); i++) {
            TableColumn dataColumn = tcs.get(i);

            if (i == 0) {
                Callback<TableColumn<ArrayList, Color>, TableCell<ArrayList, Color>> cellFactoryPane = buildCallbackPane();
                dataColumn.setCellFactory(cellFactoryPane);
            } else {
                Callback<TableColumn<ArrayList, String>, TableCell<ArrayList, String>> cellFactoryTextFieldTableCell = buildCallbackTextFieldTableCell();
                dataColumn.setCellFactory(cellFactoryTextFieldTableCell);
            }

        }

        final VBox vbox = new VBox();

        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, tableView);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);

        stage.show();
    }

    private ObservableList<TableColumn> generateTableViewColumns() {
        ObservableList<TableColumn> tableViewColumns = FXCollections.observableArrayList();
        TableColumn firstDataColumn = new TableColumn<>("Activity");
        TableColumn secondDataColumn = new TableColumn<>("Class A");
        TableColumn thirdDataColumn = new TableColumn<>("Class B");

        firstDataColumn.setMinWidth(80);
        secondDataColumn.setMinWidth(130);
        thirdDataColumn.setMinWidth(130);

        tableViewColumns.add(firstDataColumn);
        tableViewColumns.add(secondDataColumn);
        tableViewColumns.add(thirdDataColumn);        

        return tableViewColumns;
    }

    private ObservableList<ArrayList> generateTableViewRows() {
        int max = 6;
        ObservableList<ArrayList> tableViewRows = FXCollections.observableArrayList();
        for (int i = 1; i < max; i++) {
            ArrayList dataRow = new ArrayList<>();

            Color value1 = Color.GREEN;
            String value2 = "A" + i;
            String value3 = "B" + i;

            dataRow.add(value1);
            dataRow.add(value2);
            dataRow.add(value3);

            tableViewRows.add(dataRow);
        }
        return tableViewRows;
    }

    private Callback<TableColumn.CellDataFeatures<ArrayList, Color>, ObservableValue<Color>> buildCallbackColor(int index) {
        Callback<TableColumn.CellDataFeatures<ArrayList, Color>, ObservableValue<Color>> cellValueFactory = new Callback<TableColumn.CellDataFeatures<ArrayList, Color>, ObservableValue<Color>>() {
            @Override
            public ObservableValue<Color> call(TableColumn.CellDataFeatures<ArrayList, Color> param) {
                return new SimpleObjectProperty(param.getValue().get(index));
            }
        };
        return cellValueFactory;
    }

    private Callback<TableColumn.CellDataFeatures<ArrayList, String>, ObservableValue<String>> buildCallbackString(int index) {
        Callback<TableColumn.CellDataFeatures<ArrayList, String>, ObservableValue<String>> cellValueFactory = new Callback<TableColumn.CellDataFeatures<ArrayList, String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(TableColumn.CellDataFeatures<ArrayList, String> param) {
                return new SimpleStringProperty((String) param.getValue().get(index));
            }
        };
        return cellValueFactory;
    }

    private Callback<TableColumn<ArrayList, Color>, TableCell<ArrayList, Color>> buildCallbackPane() {
        Callback<TableColumn<ArrayList, Color>, TableCell<ArrayList, Color>> cellFactory = new Callback<TableColumn<ArrayList, Color>, TableCell<ArrayList, Color>>() {
            @Override
            public TableCell call(TableColumn tableColumn) {
                double cellWidth = tableColumn.getMinWidth();
                double cellHeight = 35;

                TableCell tableCell = new TableCell<Object, Color>() {
                    @Override
                    protected void updateItem(Color item, boolean empty) {
                        super.updateItem(item, empty);

                        if (empty) {
                            setText(null);
                            setGraphic(null);
                        } else {
                            Pane p = new Pane();
                            p.setPrefSize(cellWidth, cellHeight);
                            Canvas canvasRectLayerColor = new Canvas();
                            p.getChildren().add(canvasRectLayerColor);
                            canvasRectLayerColor.setWidth(20);
                            canvasRectLayerColor.setHeight(20);
                            GraphicsContext gc = canvasRectLayerColor.getGraphicsContext2D();      
                            gc.setFill(item);
                            gc.fillRect(0, 0, canvasRectLayerColor.getWidth(), canvasRectLayerColor.getHeight());
                            setGraphic(p);
                        }
                    }
                };

                return tableCell;
            }
        };

        return cellFactory;
    }

    private Callback<TableColumn<ArrayList, String>, TableCell<ArrayList, String>> buildCallbackTextFieldTableCell() {
        Callback<TableColumn<ArrayList, String>, TableCell<ArrayList, String>> cellFactory = new Callback<TableColumn<ArrayList, String>, TableCell<ArrayList, String>>() {
            @Override
            public TableCell call(TableColumn tc) {
                TextFieldTableCell tftc = new TextFieldTableCell(new StringConverter() {
                    @Override
                    public String toString(Object t) {
                        return t.toString();
                    }

                    @Override
                    public Object fromString(String string) {
                        return string;
                    }
                });

                return tftc;
            }
        };
        return cellFactory;
    }

}

希望这个帮助,即使它已经很晚了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 2017-12-13
    • 2017-09-26
    相关资源
    最近更新 更多