JavaFx - 在包含ObservableList的TableView中显示对象

时间:2014-11-27 08:51:50

标签: javafx tableview observablelist

我有一个班级Person,其中包含ObservableList<Car>。现在我想在TableView中显示数据,使其如下所示:

First Name | Last Name | Car
-----------+-----------+---------
John       | Doe       | BMW
John       | Doe       | Audi
Walter     | Johnson   | Chrysler

如何让JavaFX提取类Person列表并为该列表中的每个项创建一行?

1 个答案:

答案 0 :(得分:0)

最简单的方法是创建一个包含Car和所有者的新类CarOfPerson:

class CarOfPerson {
    Person myOwner;
    Car    myCar;
    public CarOfPerson(Car car, Person person) {
        myOwner = person;
        myCar = car;
    }
    public Person getOwner() { return myOwner; }
    public Car getCar() { return myCar; }
}

此类现在可以用作表项。因此,如果您使用这些实例创建可观察列表,则可以将表设置为:

    TableColumn<CarOfPerson,String> c1 = new TableColumn<CarOfPerson,String>("first");
    c1.setCellValueFactory(p -> p.getValue().getOwner().firstNameProperty());
    table.getColumns().add(c1);

    TableColumn<CarOfPerson,String> c2 = new TableColumn<CarOfPerson,String>("last");
    c2.setCellValueFactory(p -> p.getValue().getOwner().lastNameProperty());
    table.getColumns().add(c2);

    TableColumn<CarOfPerson,String> c3 = new TableColumn<CarOfPerson,String>("car");
    c3.setCellValueFactory(p -> p.getValue().getCar().typeProperty());
    table.getColumns().add(c3);

现在的主要挑战是:

  1. 从所有人员中创建一个CarOfPerson列表,但缺点是需要构建一个可能庞大的单独实例列表,如果进行任何更改,很难与人员列表保持同步。
  2. 创建ObservableList类型的视图,根据需要动态创建CarOfPerson对象:

    ObservableList<CarOfPerson> list = new ObservableListBase<CarOfPerson>(){
        ObservableList<Person> myPersons = persons;
        boolean observed = false;
    
        @Override
        public CarOfPerson get(int index) {
            System.out.println("get "+index);
            for (Person person : myPersons) {
                if (person.getNumberOfCars() > index) return new CarOfPerson(person.getCar(index), person);
                index -= person.getNumberOfCars();
            }
            return new CarOfPerson(new Car("null"), new Person("N", "N"));
        }
    
        @Override
        public int size() {
            if (!observed) {
                myPersons.addListener((ListChangeListener.Change<? extends TableInVBox.Person> c) -> {
                    beginChange();
                    nextAdd(0, Integer.MAX_VALUE);
                    endChange();
                });
                observed = true;
            }
            int size = 0;
            for (Person person : myPersons) size += person.getNumberOfCars();
            return size;
        } 
    };
    
  3. 这将成为潜在的可观察CarOfPersons的巨大列表。但是这些实例中的每一个都只会根据需要生成,如果在当前表中显示....

    观察myPersons将更新TableView以立即显示人员列表中的更改。因此,添加,删除人员或姓名将反映在表格中。

    enter image description here

    当然我的实现效率非常低,迭代所有人员直到正确的索引,但可以优化。它的暗示。