You need to update your data object model to represent the data you want displayed in the TableView. So in the code below, I've modified your WorkTime
class to be more suited to display.
So for your WorkTime
class, I've updated each field to a Property
so the TableView
can find it.
I refactored the WorkTime
class a bit as well. The constructor now accepts the HourMinute
objects and parses the data from those when creating the WorkTime
object.
public class WorkTime {
// All fields should be converted to properties
private IntegerProperty startHour = new SimpleIntegerProperty();
private IntegerProperty startMinute = new SimpleIntegerProperty();
private IntegerProperty endHour = new SimpleIntegerProperty();
private IntegerProperty endMinute = new SimpleIntegerProperty();
private IntegerProperty totalHours = new SimpleIntegerProperty();
private IntegerProperty totalMinutes = new SimpleIntegerProperty();
private ObjectProperty<LocalDate> localDate = new SimpleObjectProperty<>();
public WorkTime(HourMinute start, HourMinute end, HourMinute total, LocalDate localDate) {
// Accept the start and end times as HourMinute objects and extract each value from them.
this.startHour.set(start.getHour());
this.startMinute.set(start.getMinute());
this.endHour.set(end.getHour());
this.endMinute.set(end.getMinute());
this.totalHours.set(total.getHour());
this.totalMinutes.set(total.getMinute());
this.localDate.set(localDate);
}
public int getStartHour() {
return startHour.get();
}
public IntegerProperty startHourProperty() {
return startHour;
}
public int getStartMinute() {
return startMinute.get();
}
public IntegerProperty startMinuteProperty() {
return startMinute;
}
public int getEndHour() {
return endHour.get();
}
public IntegerProperty endHourProperty() {
return endHour;
}
public int getEndMinute() {
return endMinute.get();
}
public IntegerProperty endMinuteProperty() {
return endMinute;
}
public int getTotalHours() {
return totalHours.get();
}
public IntegerProperty totalHoursProperty() {
return totalHours;
}
public int getTotalMinutes() {
return totalMinutes.get();
}
public IntegerProperty totalMinutesProperty() {
return totalMinutes;
}
public LocalDate getLocalDate() {
return localDate.get();
}
public ObjectProperty<LocalDate> localDateProperty() {
return localDate;
}
}
Now, back in your main class, you need to update your TableView
definition to define what type of data it is going to hold. In this case, it is set to display a list of WorkTime
objects:
TableView<WorkTime> tableView = new TableView<>();
The TableColumn
objects also need to be updated to define what data type to display. This will take two parameters: the overall object type, and the data type the cell will hold:
TableColumn<WorkTime, Integer> colStartHour = new TableColumn<>("Start Hour");
TableColumn<WorkTime, String> colStartMinute = new TableColumn<>("Start Minute");
TableColumn<WorkTime, Integer> colEndHour = new TableColumn<>("End Hour");
TableColumn<WorkTime, String> colEndMinute = new TableColumn<>("End Minute");
TableColumn<WorkTime, Integer> colTotalHours = new TableColumn<>("Total Hours");
TableColumn<WorkTime, String> colTotalMinutes = new TableColumn<>("Total Minutes");
The last step is to define the CellValueProperty
for each column. This is where you tell JavaFX exactly where in your WorkTime
class it will find the data:
colStartHour.setCellValueFactory(new PropertyValueFactory<>("startHour"));
colStartMinute.setCellValueFactory(new PropertyValueFactory<>("startMinute"));
colEndHour.setCellValueFactory(new PropertyValueFactory<>("endHour"));
colEndMinute.setCellValueFactory(new PropertyValueFactory<>("endMinute"));
colTotalHours.setCellValueFactory(new PropertyValueFactory<>("totalHours"));
colTotalMinutes.setCellValueFactory(new PropertyValueFactory<>("totalMinutes"));
You'll see the new PropertyValueFactory<>("propertyName")
section defines the name of the property defined in WorkTime
. JavaFX will get the value of that property, and display it in the cell.
So this works will any datatype you need, as long as you defined the column to expect that datatype.
That is all there is to it! This will now allow you to display the data properly.
Below is a simple MCVE that uses the WorkTime
class above.
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableArray;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.time.LocalDate;
import java.util.List;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Create sample WorkTime objects. Store them in an ObservableArrayList so the TableView can display them
ObservableList<WorkTime> workTimes = FXCollections.observableArrayList();
workTimes.add(new WorkTime(
new HourMinute(1, 2),
new HourMinute(1, 2),
new HourMinute(1, 2),
LocalDate.now()));
workTimes.add(new WorkTime(
new HourMinute(1, 2),
new HourMinute(1, 2),
new HourMinute(1, 2),
LocalDate.now()));
workTimes.add(new WorkTime(
new HourMinute(1, 2),
new HourMinute(1, 2),
new HourMinute(1, 2),
LocalDate.now()));
// Simple UI
VBox root = new VBox(10);
root.setPadding(new Insets(10));
root.setAlignment(Pos.TOP_CENTER);
// Create a TableView
TableView<WorkTime> tableView = new TableView<>();
// Create each column
TableColumn<WorkTime, Integer> colStartHour = new TableColumn<>("Start Hour");
TableColumn<WorkTime, String> colStartMinute = new TableColumn<>("Start Minute");
TableColumn<WorkTime, Integer> colEndHour = new TableColumn<>("End Hour");
TableColumn<WorkTime, String> colEndMinute = new TableColumn<>("End Minute");
TableColumn<WorkTime, Integer> colTotalHours = new TableColumn<>("Total Hours");
TableColumn<WorkTime, String> colTotalMinutes = new TableColumn<>("Total Minutes");
// Set the CellValueFactory for each column to define what data to use for each column. This should match the
// property set in the WorkTime class
colStartHour.setCellValueFactory(new PropertyValueFactory<>("startHour"));
colStartMinute.setCellValueFactory(new PropertyValueFactory<>("startMinute"));
colEndHour.setCellValueFactory(new PropertyValueFactory<>("endHour"));
colEndMinute.setCellValueFactory(new PropertyValueFactory<>("endMinute"));
colTotalHours.setCellValueFactory(new PropertyValueFactory<>("totalHours"));
colTotalMinutes.setCellValueFactory(new PropertyValueFactory<>("totalMinutes"));
// Add the columns to the TableView
tableView.getColumns().addAll(colStartHour, colStartMinute, colEndHour, colEndMinute, colTotalHours, colTotalMinutes);
// Set the people list as the data for the TableView
tableView.setItems(workTimes);
// Add the TableView to the scene
root.getChildren().add(tableView);
// Finish building the stage and show it
primaryStage.setTitle("TableView Sample");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
Answer to your side question
This is simple to do as well. Just add another property to your WorkTime
class:
private StringProperty dateString = new SimpleStringProperty();
public String getDateString() {
return year + "-" + month + "-" + date;
}
Then add the column to your TableView
and set the appropriate CelLValueProperty
.