JavaFX 2 TableView: различная фабрика ячеек в зависимости от данных внутри ячейки
Я пытаюсь использовать представление таблицы для отображения / редактирования пар "ключ = значение". Таким образом, таблица должна иметь два столбца : "ключ" и "значение". Key - это обычная строка, а value может быть чем угодно. Моя проблема в том, что тип данных значений может отличаться от строки к строке. В принципе, я хотел использовать флажки для логических значений и вариантов для списков. Я нашел способ отобразить весь столбец таблицы с флажками или вариантами, установив ячейку фабрика:
final TableColumn<FieldValue, Field> valueColumn = new TableColumn<>("Value");
valueColumn.setCellFactory(new Callback<TableColumn<FieldValue, Field>, TableCell<FieldValue, Field>>() {
@Override
public TableCell<FieldValue, Field> call(final TableColumn<FieldValue, Field> column) {
// if (value instanceof Boolean)
return new CheckBoxTableCell<>();
}
});
но мне нужно иметь возможность вставлять условие, основанное на типе элемента, который будет отображаться внутри ячейки. Другими словами, некоторая фабрика ячеек на уровне ячеек, а не на уровне столбцов. И это оценивает мое состояние во время рендеринга. Я до сих пор не нашел никакого решения. Может, у кого-то есть правильные методы для осуществления такого перевода? Может быть, какой-то сторонний datagrid?
1 ответов
Вот таблица, отображающая пары строк и объектов различных типов.
фабрика пользовательских ячеек используется для обработки отображения различных типов объектов (путем выполнения проверки типа объекта и отображения соответствующего текста или графики).
import javafx.application.*;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ObservableValue;
import javafx.collections.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.Pair;
public class PairTable extends Application {
public static final String NAME_COLUMN_NAME = "Name";
public static final String VALUE_COLUMN_NAME = "Value";
final TableView<Pair<String, Object>> table = new TableView<>();
public static void main(String[] args) throws Exception {
launch(args);
}
public void start(final Stage stage) throws Exception {
// model data
ObservableList<Pair<String, Object>> data = FXCollections.observableArrayList(
pair("Song", "Bach Cello Suite 2"),
pair("Image", new Image("http://upload.wikimedia.org/wikipedia/en/9/99/Bach_Seal.jpg")),
pair("Rating", 4),
pair("Classic", true),
pair("Song Data", new byte[]{})
);
table.getItems().setAll(data);
table.setPrefHeight(275);
// table definition
TableColumn<Pair<String, Object>, String> nameColumn = new TableColumn<>(NAME_COLUMN_NAME);
nameColumn.setPrefWidth(100);
TableColumn<Pair<String, Object>, Object> valueColumn = new TableColumn<>(VALUE_COLUMN_NAME);
valueColumn.setSortable(false);
valueColumn.setPrefWidth(150);
nameColumn.setCellValueFactory(new PairKeyFactory());
valueColumn.setCellValueFactory(new PairValueFactory());
table.getColumns().setAll(nameColumn, valueColumn);
valueColumn.setCellFactory(new Callback<TableColumn<Pair<String, Object>, Object>, TableCell<Pair<String, Object>, Object>>() {
@Override
public TableCell<Pair<String, Object>, Object> call(TableColumn<Pair<String, Object>, Object> column) {
return new PairValueCell();
}
});
// layout the scene.
final StackPane layout = new StackPane();
layout.getChildren().setAll(table);
Scene scene = new Scene(layout);
stage.setScene(scene);
stage.show();
}
private Pair<String, Object> pair(String name, Object value) {
return new Pair<>(name, value);
}
}
class PairKeyFactory implements Callback<TableColumn.CellDataFeatures<Pair<String, Object>, String>, ObservableValue<String>> {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Pair<String, Object>, String> data) {
return new ReadOnlyObjectWrapper<>(data.getValue().getKey());
}
}
class PairValueFactory implements Callback<TableColumn.CellDataFeatures<Pair<String, Object>, Object>, ObservableValue<Object>> {
@SuppressWarnings("unchecked")
@Override
public ObservableValue<Object> call(TableColumn.CellDataFeatures<Pair<String, Object>, Object> data) {
Object value = data.getValue().getValue();
return (value instanceof ObservableValue)
? (ObservableValue) value
: new ReadOnlyObjectWrapper<>(value);
}
}
class PairValueCell extends TableCell<Pair<String, Object>, Object> {
@Override
protected void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
if (item instanceof String) {
setText((String) item);
setGraphic(null);
} else if (item instanceof Integer) {
setText(Integer.toString((Integer) item));
setGraphic(null);
} else if (item instanceof Boolean) {
CheckBox checkBox = new CheckBox();
checkBox.setSelected((boolean) item);
setGraphic(checkBox);
} else if (item instanceof Image) {
setText(null);
ImageView imageView = new ImageView((Image) item);
imageView.setFitWidth(100);
imageView.setPreserveRatio(true);
imageView.setSmooth(true);
setGraphic(imageView);
} else {
setText("N/A");
setGraphic(null);
}
} else {
setText(null);
setGraphic(null);
}
}
}