Reputation: 245
I've got problem with TableView in JavaFX.
Creating tables from existing class with all fields defined is easy.
But I'm wondering if it is possible to make table and add data from List?
I've made something like this but it kinda doesn't work.
@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);
});
It didn't insert any data. Is something like that even possible?
Upvotes: 3
Views: 15029
Reputation: 3186
You can do this by replacing String
to StringProperty
in the List
:
@FXML
private TableView<List<StringProperty>> testTable;
then:
TableColumn<List<StringProperty>, String> coll = new TableColumn<>("one");
add the cellValueFactories:
col1.setCellValueFactory(data -> data.getValue().get(0));
col2.setCellValueFactory(data -> data.getValue().get(1));
.
.
and so on.
This means the first element of the list will be used in col1
, the second element of the list will be used in col2
.
Then you can populate the list like:
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);
It is doable this way but I would say it is a very bad practice.
Upvotes: 2
Reputation: 49
As a little piece for my work i need a TableView with dynamically filled data from a List. I looked at some other samples out there in StackOverflow and also at the Oracle tutorials. But nothing fits my needs.
To meet my necessity i puzzled the different solutions together. See the working sample below.
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;
}
}
Hope this one help even it is quite late.
Upvotes: 0