ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

让LocalDate显示在Javafx的Tableview中

2019-10-02 21:01:24  阅读:408  来源: 互联网

标签:localdate java javafx tableview


我一直在处理我的应用程序的一部分,该应用程序允许用户输入他们学校起飞的假期并将其保存到文件中.从文件中读取假日的名称和日期(存储为LocalDate对象)并存储在假日对象中并放入可观察的arraylist中.

这是主控制器:

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Optional;


public class Controller {
    @FXML
    private BorderPane mainGridPane;
    private ArrayList<Job> jobs = new ArrayList<>();
    private static XSSFRow row;
    private boolean fileClosed = false;
    @FXML
    private DatePicker employeeStartDate;
    @FXML
    private Label evaluation40;
    @FXML
    private Label evaluation80;
    @FXML
    private Label evaluation120;
    @FXML
    private DatePicker summerStart;
    @FXML
    private DatePicker summerEnd;
    @FXML
    private DatePicker fallStart;
    @FXML
    private DatePicker fallEnd;
    @FXML
    private TableView<Holiday> tableView;

    private HolidayData data;

    public void initialize() throws IOException {
        data = new HolidayData();
        data.loadHolidays();
        tableView.setItems(data.getHolidays());

    }

这是假期课程:

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import java.time.LocalDate;

public class Holiday {
    private SimpleStringProperty name = new SimpleStringProperty();
    private ObjectProperty<LocalDate> date;


    public Holiday(String name, LocalDate date) {
        this.name.set(name);
        this.date = new SimpleObjectProperty<>(date);
    }

    public String getName() {
        return name.get();
    }

    public SimpleStringProperty nameProperty() {
        return name;
    }

    public LocalDate getDate() {
        return date.get();
    }

    public ObjectProperty<LocalDate> dateProperty() {
        return date;
    }

这是HolidayData类,负责从文件和生成以及可观察的arraylist读取数据:

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;

public class HolidayData {
     private static HolidayData instance = new HolidayData();
     private static String fileName = "schoolHolidays.txt";
     private DateTimeFormatter formatter;

     private ObservableList<Holiday> holidays;

     public HolidayData(){
         formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
     }

    public static HolidayData getInstance() {
        return instance;
    }

    public static String getFileName() {
        return fileName;
    }

    public ObservableList<Holiday> getHolidays(){
         return holidays;
    }

    public void addHoliday(Holiday holiday){
         holidays.add(holiday);
    }


    public void loadHolidays() throws IOException {
        holidays = FXCollections.observableArrayList();
        Path path = Paths.get(fileName);
        BufferedReader br = Files.newBufferedReader(path);

        String input;
        try{
            while((input = br.readLine()) != null){
                String[] holidayPieces = input.split("\t");

                String name = holidayPieces[0];
                String dateString =  holidayPieces[1];

                LocalDate date = LocalDate.parse(dateString, formatter);
                Holiday holiday = new Holiday(name, date);
                holidays.add(holiday);
            }
        }catch(IOException e) {
            e.printStackTrace();
        } finally{
            if(br != null){
                br.close();
            }
        }
    }

    public void storeHolidays()throws IOException{
        Path path = Paths.get(fileName);
        BufferedWriter bw = Files.newBufferedWriter(path);
        try {
            Iterator<Holiday> iter = holidays.iterator();
            while(iter.hasNext()){
                Holiday holiday = iter.next();
                bw.write(String.format("%s\t%s", holiday.getName(), holiday.getDate().format(formatter)));
                bw.newLine();
            }
        }finally {
            if (bw != null){
                bw.close();
            }

        }
    }

    public void deleteHoliday(Holiday holiday){
        holidays.remove(holiday);
    }
}

这是FXML文件的tableView部分:

<TableView fx:id="tableView">
    <columnResizePolicy>
        <TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
    </columnResizePolicy>
    <columns>
        <TableColumn text="Holiday Name">
            <cellFactory>
                <PropertyValueFactory property="name"/>
            </cellFactory>
        </TableColumn>
        <TableColumn text="Date">
            <cellFactory>
                <PropertyValueFactory property="date" />
            </cellFactory>
        </TableColumn>
    </columns>
</TableView>

我遇到的问题是java.lang.ClassCastException,表示无法将表列强制转换为某个对象,我认为该对象是LocalDate对象.我使用SimpleObjectProperty将它数据绑定到FXML文件,但我似乎无法让它工作.我能想到的另一件事就是在Holiday中将日期设为SimpleStringProperty并将其转换为我代码中所有其他部分的LocalDate,但这似乎是不必要的.我很感激任何人都能给我的见解.

解决方法:

TL; DR版:您将cellValueFactory与cellFactory混淆.例如,参见this tutorial,以获得对差异的一个很好的解释,这对于下面这个特定的例子进行了总结.

表列的cellValueFactory是一个对象,它告诉列要在单元格中显示哪些值,或者更准确地说是如何从表示每行的对象中获取这些值.这由Callback< CellDataFeatures< Holiday,LocalDate>,ObservableProperty< LocalDate>>表示,即映射CellDataFeatures< Holiday,LocalDate>的功能.到ObservableValue< LocalDate>.所以在Java代码中你会这样做

dateColumn.setCellValueFactory(holidayRowData -> holidayRowData.getValue().dateProperty());

或者,如果您更喜欢使用(有些遗留的)PropertyValueFactory类,您可以这样做

dateColumn.setCellValueFactory(new PropertyValueFactory<>("date"));

后一版本具有(许多缺点,但一个)优点,它也可以在FXML中完成.但请注意,您需要cellValueFactory,而不是cellFactory.所以你的FXML应该是

<TableView fx:id="tableView">
    <columnResizePolicy>
        <TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
    </columnResizePolicy>
    <columns>
        <TableColumn text="Holiday Name">
            <cellValueFactory>
                <PropertyValueFactory property="name"/>
            </cellValueFactory>
        </TableColumn>
        <TableColumn text="Date">
            <cellValueFactory>
                <PropertyValueFactory property="date" />
            </cellValueFactory>
        </TableColumn>
    </columns>
</TableView>

相反,cellFactory是一个告诉列如何显示数据的对象.它由Callback< TableColumn< Holiday,LocalDate>,TableCell< Holiday,LocalDate>>表示,即映射TableColumn< Holiday,LocalDate>的功能.到TableCell< Holiday,LocalDate>.发生ClassCastException是因为您设置的单元格工厂将要传递TableColumn,但是期望接收CellDataFeatures,因此当它尝试对其进行处理时,转换将失败.

除了单元格值工厂之外,您可能还需要一个单元工厂,以便您可以控制日期的显示方式(例如,控制用于它的格式).如果您为日期列指定一个fx:id,请说< TableColumn fx:id =“dateColumn”>,然后将其注入控制器

@FXML
private TableColumn<Holiday, LocalDate> dateColumn ;

然后在控制器的initialize方法中,你可以这样做:

public void initialize() throws IOException {
    data = new HolidayData();
    data.loadHolidays();
    tableView.setItems(data.getHolidays());

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
    dateColumn.setCellFactory(column -> new TableCell<Holiday, LocalDate>() {
        @Override
        protected void updateItem(LocalDate date, boolean empty) {
            super.updateItem(date, empty);
            if (empty) {
                setText("");
            } else {
                setText(formatter.format(date));
            }
        }
    });
}

标签:localdate,java,javafx,tableview
来源: https://codeday.me/bug/20191002/1844583.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有