我是JavaFX的新手,想要创建一个TableView。
我已经使用包含ArrayList的Person类选择了以下示例
OneToMany-relation(1:n)应该像这样显示。
╔════╤════════════════════╤════════════════════╗
║ │ name │ car ║
║ id ├──────────┬─────────┼──────────┬─────────╢
║ │ forname │ surname │ brand │ model ║
╠════╪══════════╪═════════╪══════════╪═════════╣
║ 0 │ John │ Doe │ Audi │ A3 ║
║ │ │ │ VW │ Golf3 ║
╟────┼──────────┼─────────┼──────────┼─────────╢
║ 1 │ Jane │ Doe │ BMW │ i5 ║
╚════╧══════════╧═════════╧══════════╧═════════╝
class Person
{
private SimpleStringProperty forname;
private SimpleStringProperty surname;
private List<Car> cars;
public Person(String forname, String surname, List<Car> cars)
{
this.forname.set(forname);
this.surname.set(surname);
this.lehrveranstaltungen = lehrveranstaltungen;
}
public Person()
{
this("","",new ArrayList<Car>());
}
public String getForname()
{
return forname.get();
}
public String getSurname()
{
return surname.get();
}
public List<Car> getCars()
{
return cars;
}
}
汽车类与此类似
official docs
但是,如何使用汽车类的属性填充汽车的子列?它只适用于1个属性。我是否必须将汽车的属性声明为每个子列?
答案 0 :(得分:2)
最简单的方法是为&#34; Brand&#34;制作数据值。列和&#34;模型&#34;列列出汽车列表;然后使用单元工厂将单元格的文本设置为每个汽车的相应值,并用换行符分隔。
这有一些缺点:没有绝对保证列表单元格中具有多行文本的所有行的高度将相等,因此您无法完全保证这些行将完全对齐。我认为它适用于这个用例。如果您想要更多控制权,可以创建一个VBox
作为单元格的图形,并使用单个标签填充它,每辆车一次。这样你就可以根据需要控制标签的高度;可能你可以设置标签的样式以产生边框的效果,所以它看起来真的像'#34; subcells&#34;。
此外,如果在显示表格时更改了数据,这些单元格将不会更新,但这更多是因为您对汽车使用普通List<Car>
。这可以通过使用适当的ObservableList
来修复,如果需要,也可以使用提取器。
最后,这只是使用一个单元格来呈现汽车品牌和汽车模型的每个列表,因此您无法选择单个品牌或型号。
简单的解决方案如下:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class TableViewWithList extends Application {
// Cell implementation used later to create cells with multiline text
// from a cell item that is a List
public static class MultilineCell<S, T, U extends List<T>> extends TableCell<S, U> {
// function mapping each element of the list to a string
private final Function<T, String> textMapper ;
public MultilineCell(Function<T,String> textMapper) {
this.textMapper = textMapper ;
}
@Override
protected void updateItem(U items, boolean empty) {
super.updateItem(items, empty);
if (empty) {
setText(null);
} else {
// map each element of the list to a string, and join them with
// a new line between each
setText(
items.stream()
.map(textMapper)
.collect(Collectors.joining("\n"))
);
}
}
}
// Utility method to create a table column with a given title and function mapping
// the row value to a property to be used as the data for cells in that column
private <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col ;
}
@Override
public void start(Stage primaryStage) {
TableColumn<Person, List<Car>> brandCol = column("Brand",
person -> new SimpleObjectProperty<>(person.getCars()));
TableColumn<Person, List<Car>> modelCol = column("Model",
person -> new SimpleObjectProperty<>(person.getCars()));
brandCol.setCellFactory(tc -> new MultilineCell<>(Car::getBrand));
modelCol.setCellFactory(tc -> new MultilineCell<>(Car::getModel));
TableView<Person> table = new TableView<>();
TableColumn<Person, Void> nameCol = new TableColumn<>("Name");
TableColumn<Person, Void> carCol = new TableColumn<>("Car");
table.getColumns().add(nameCol);
table.getColumns().add(carCol);
nameCol.getColumns().add(column("First Name", Person::firstNameProperty));
nameCol.getColumns().add(column("Last Name", Person::lastNameProperty));
carCol.getColumns().add(brandCol);
carCol.getColumns().add(modelCol);
Car a3 = new Car("Audi", "A3");
Car golf = new Car("VW", "Golf GTI");
Car i5 = new Car("BMW", "i5");
table.getItems().addAll(
new Person("John", "Doe", a3, golf),
new Person("Jane", "Doe", i5)
);
Scene scene = new Scene(table);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class Car {
private final String brand ;
private final String model ;
public Car(String brand, String model) {
this.brand = brand;
this.model = model;
}
public String getBrand() {
return brand;
}
public String getModel() {
return model;
}
}
public static class Person {
private final StringProperty firstName = new SimpleStringProperty();
private final StringProperty lastName = new SimpleStringProperty();
private final List<Car> cars ;
public Person(String firstName, String lastName, Car...cars) {
setFirstName(firstName);
setLastName(lastName);
this.cars = new ArrayList<>(Arrays.asList(cars));
}
public List<Car> getCars() {
return cars ;
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final String lastName) {
this.lastNameProperty().set(lastName);
}
}
public static void main(String[] args) {
launch(args);
}
}
呈现为