【问题标题】:How to populate a TableView in JavaFX from an array list如何从数组列表中填充 JavaFX 中的 TableView
【发布时间】:2019-01-24 14:53:02
【问题描述】:

我有一个ArrayList,其中的数据是从 Excel 文件中读取的。我现在想在我的 JavaFX 应用程序中创建一个 TableView,它从已创建的 ArrayList 中填充。我有一个类,其中包含所有读取的地址数据,例如建筑物编号、街道名称等,但我似乎无法获取这些数据并将其放入表视图中,它只是空白。

这是我到目前为止生成的代码:

List<AddressDetails> addressList = ReadExcel.readExcel();

TableView<AddressDetails> table = new TableView<>();
ObservableList<AddressDetails> addresses = FXCollections.observableArrayList(addressList);

TableColumn<AddressDetails, String> buildNameCol 
  = new TableColumn<AddressDetails, String>("Building Name");
buildNameCol.setCellValueFactory(new PropertyValueFactory<AddressDetails, String>("buildName"));

TableColumn<AddressDetails, Double> buildNumCol
  = new TableColumn<AddressDetails, Double>("Building Number");
buildNumCol.setCellValueFactory(new PropertyValueFactory<AddressDetails, Double>("buildNum"));

TableColumn<AddressDetails, String> streetCol
  = new TableColumn<AddressDetails, String>("Street Name");
streetCol.setCellValueFactory(new PropertyValueFactory<AddressDetails, String>("streetName"));

TableColumn<AddressDetails, String> cityCol
  = new TableColumn<AddressDetails, String>("City");
cityCol.setCellValueFactory(new PropertyValueFactory<AddressDetails, String>("city"));

TableColumn<AddressDetails, String> postCol 
  = new TableColumn<AddressDetails, String>("Postcode");
postCol.setCellValueFactory(new PropertyValueFactory<AddressDetails, String>("postCode"));

TableColumn<AddressDetails, String> countryCol
  = new TableColumn<AddressDetails, String>("Country");
countryCol.setCellValueFactory(new PropertyValueFactory<AddressDetails, String>("country"));

table.getColumns().addAll(buildNameCol, buildNumCol, streetCol, cityCol, postCol, countryCol); 
table.setItems(addresses);

这是我的AddressDetails班级:

public class AddressDetails {

    private String buildName;
    private double buildNum;
    private String streetName;
    private String city;
    private String postCode;
    private String country;

    public AddressDetails() {

    }

    public String getBuildName() {
        return buildName;
    }

    public void setBuildName(String buildName) {
        this.buildName = buildName;
    }

    public double getBuildNum() {
        return buildNum;
    }

    public void setBuildNum(double buildNum) {
        this.buildNum = buildNum;
    }

    public String getStreetName() {
        return streetName;
    }

    public void setStreetName(String streetName) {
        this.streetName = streetName;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getPostCode() {
        return postCode;
    }

    public void setPostCode(String postCode) {
        this.postCode = postCode;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

这是将excel文件中的地址添加到ArrayList中的excel阅读器:

public class ReadExcel {  

public static List<AddressDetails> readExcel() {

    List<AddressDetails> addressList = null;

    try {

        Workbook workbook = WorkbookFactory.create(new FileInputStream(FileSelector.getSelectedFile()));

        // Get the first sheet from the excel file
        Sheet sheet = workbook.getSheetAt(0);
        if (sheet != null) {
            addressList = readExcelSheet(sheet);

        }

    } catch (EncryptedDocumentException | IOException | ParseException e) {
        e.printStackTrace();

    }

    if (addressList == null)
        addressList = Collections.emptyList();

    return addressList;

}

private static List<AddressDetails> readExcelSheet(Sheet sheet) throws ParseException {

    Iterator<Row> rowItr = sheet.iterator();
    List<AddressDetails> addressList = new ArrayList<>();

    // Iterate each row in the sheet
    while (rowItr.hasNext()) {
        AddressDetails address = new AddressDetails();
        Row row = rowItr.next();
        // First row is header so skip it
        if (row.getRowNum() <= 2) {
            continue;

        }

        Iterator<Cell> cellItr = row.cellIterator();
        // Iterate each cell in a row
        while (cellItr.hasNext()) {

            Cell cell = cellItr.next();
            int index = cell.getColumnIndex();
            switch (index) {
            case 0:
                address.setBuildName((String) getValueFromCell(cell));
                break;
            case 1:
                address.setBuildNum((double) getValueFromCell(cell));
                break;
            case 2:
                address.setStreetName((String) getValueFromCell(cell));
                break;
            case 3:
                address.setCity((String) getValueFromCell(cell));
                break;
            case 4:
                address.setPostCode((String) getValueFromCell(cell));
                break;
            case 5:
                address.setCountry((String) getValueFromCell(cell));
                break;

            }

        }

        addressList.add(address);

    }

    return addressList;

}

// Method to get cell value based on cell type
private static Object getValueFromCell(Cell cell) {
    switch (cell.getCellType()) {
    case STRING:
        return cell.getStringCellValue();

    case NUMERIC:
        return cell.getNumericCellValue();

    case BLANK:
        return "";
    default:
        return "";

    }

}

}

【问题讨论】:

  • AddressDetails addressList = new AddressDetails();我没有看到你向这个对象添加值。
  • @StephanHogenboom 抱歉,这是说 List addressList = ReadExcel.readExcel();因为这是我通过读取 excel 文件创建数组列表的地方

标签: java javafx tableview


【解决方案1】:

您的addressList 应该是List&lt;AddressDetails&gt; 而不是单个AddressDetails

import java.util.*;
import javafx.application.Application;
import javafx.collections.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class AddressView extends Application {
    private static final String APPLICATION_TITLE = "Address List";

    public static final List<Column<?>> COLUMNS = new ArrayList<>(Arrays.asList(
        new Column<String>(String.class, "buildName", "Building Name"),
        new Column<Double>(Double.class, "buildNum", "Building Number"),
        new Column<String>(String.class, "streetName", "Street Name"),
        new Column<String>(String.class, "city", "City"),
        new Column<String>(String.class, "postCode", "Postcode"),
        new Column<String>(String.class, "country", "Country")
    ));

    private static List<AddressDetails> ADDRESS_LIST = new ArrayList<>(Arrays.asList(
        new AddressDetails("Building A", 1, "Street 1", "City X", "10101", "USA"),
        new AddressDetails("Building B", 2, "Street 2", "City Y", "02020", "USA"),
        new AddressDetails("Building C", 3, "Street 3", "City X", "30303", "USA"),
        new AddressDetails("Building D", 4, "Street 4", "City Y", "04040", "USA"),
        new AddressDetails("Building E", 5, "Street 5", "City X", "50505", "USA")
    ));

    @Override
    public void start(Stage primaryStage) throws Exception {
        StackPane root = new StackPane();
        TableView<AddressDetails> table = createTable(COLUMNS, ADDRESS_LIST);
        root.getChildren().add(table);
        primaryStage.setTitle(APPLICATION_TITLE);
        primaryStage.setScene(new Scene(root, 500, 200));
        primaryStage.show();
    }

    private <E> TableView<E> createTable(List<Column<?>> columns, List<E> data) {
        TableView<E> table = new TableView<>();
        ObservableList<E> addresses = FXCollections.observableArrayList(data);
        for (Column<?> column : columns) {
            table.getColumns().add(createColumn(column));
        }

        table.setItems(addresses);
        return table;
    }

    private <E, C> TableColumn<E, C> createColumn(Column<?> column, C type) {
        TableColumn<E, C> tableColumn = new TableColumn<E, C>(column.getTitle());
        tableColumn.setCellValueFactory(new PropertyValueFactory<E, C>(column.getFieldName()));
        return tableColumn;
    }

    private <E> TableColumn<E, ?> createColumn(Column<?> column) {
        switch (column.getType().getCanonicalName()) {
            case "java.lang.Integer":
                return createColumn(column, Integer.class);
            case "java.lang.Double":
                return createColumn(column, Double.class);
            case "java.lang.String":
            default:
                return createColumn(column, String.class);
        }
    }

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

我创建了一个列类来保存列数据,以便可以动态创建列。

public class Column<T> {
    private Class<T> type;
    private String fieldName;
    private String title;

    public Column(Class<T> type, String fieldName, String title) {
        this.type = type;
        this.fieldName = fieldName;
        this.title = title;
    }

    public Class<T> getType() {
        return type;
    }

    public void setType(Class<T> type) {
        this.type = type;
    }

    public String getFieldName() {
        return fieldName;
    }

    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

另外,不要忘记在AddressDetails 中创建一个字段构造函数。

public AddressDetails(String buildName, double buildNum, String streetName, 
        String city, String postCode, String country) {
    this.buildName = buildName;
    this.buildNum = buildNum;
    this.streetName = streetName;
    this.city = city;
    this.postCode = postCode;
    this.country = country;
}

【讨论】:

  • 只是出于好奇,您为什么使用EC 以及另一个类T
  • @m0skit0 T 通常是 CLASS 模板类型的 goto,而 E 通常是 METHOD 模板类型的 goto(因此在存在 T 的情况下不要将它与 T 混淆)。我选择 C ​​来表示你传入的类的类型。这些可以是你想要的任何名称。 E 可以是(元素)DATA_TYPE,C 可以根据需要命名为 CLASS_TYPE。
猜你喜欢
  • 2015-03-31
  • 2018-10-20
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
  • 2017-11-01
  • 1970-01-01
  • 2014-10-08
  • 2018-10-14
相关资源
最近更新 更多